Array Compare in Ruby on Rails - ruby-on-rails

I have two arrays, one is two dimensional and another one dimensional as:
array1 = [["San Francisco", 8], ["New York", 3], ["Madison", 2], ["Washington", 3], ["Tulsa", 3]]
array2 = ["Durham", "Rochester", "New York", "Tulsa", "Kenner", "Washington", "Linton", "Kansas City", "San Francisco", "Madison"]
I want to compare the arrays for existence of City Name in both arrays and show total users as given in the first array (second elements) or 0 if the city is not in first array.
The output should be like this:
Durham (0)
Rochester (0)
New York (3)
Tulsa(3)
Kenner (0)
Washington (3)
...
How can I achive this in Rails?
EDIT:
Actually I have tried array1-array2 to get the differences and adding the differences to array1 with second value 0 but this didn't work for me.
Thanks in advance.

array1 is a perfect candidate to be converted to Hash.
h=Hash[array1]
array2.each{|city| puts "%s(%d)" % [city, h[city]||0] }

Using Array#assoc:
array1 = [["San Francisco", 8], ["New York", 3], ["Madison", 2], ["Washington", 3], ["Tulsa", 3]]
array2 = ["Durham", "Rochester", "New York", "Tulsa", "Kenner", "Washington", "Linton", "Kansas City", "San Francisco", "Madison"]
mapping = Hash[array1]
mapping.default = 0
array2.each do |city|
puts "#{city} (#{mapping[city]})"
end

I'd suggest looking at array uniq, and intersection (&).

Related

From array to 2D array devided by 2 values

I'm having an array:
arr =["112000666", "10", "111282637", "15", "111342625", "12", "112000674",
"11", "111488203", "18", "111237150", "20"]
Is there any way to make a 2D array and divided by 2 values? Something like this:
[["112000666", "10"], ["111282637", "15"], ["111342625", "12"],
["112000674", "11"], ["111488203", "18"], ["111237150", "20"]]
The number of elements will always be even.
For rails you can use in_groups_of method:
arr.in_groups_of(2)
#=> [["112000666", "10"], ["111282637", "15"], ["111342625", "12"],
# ["112000674", "11"], ["111488203", "18"], ["111237150", "20"]]
Pure Ruby:
arr.each_slice(2).to_a
#=> [["112000666", "10"], ["111282637", "15"], ["111342625", "12"],
# ["112000674", "11"], ["111488203", "18"], ["111237150", "20"]]
See Enumerable#each_slice.

Create list of lists from list of json objects ruby

I have a list of json objects something like this:
test = [{"a": 1, "b": 2, "c": 3}, {"a": 4, "b": 5, "c":6}]
I want to fetch the fields 'a' and 'c' from the above test list to create a list of list something like this:
[[1, 4], [3, 6]]
The idea is to make a list of all the values of a, then the values of c.
When I am using pluck:
test.pluck(:a, :c)
I am getting output like this:
[[1, 3], [4, 6]]
One approach I tried which is working fine.
res = []
res << test.pluck(:a)
res << test.pluck(:c)
But I am thinking it would be better if I get one or two liner solution,
with or without inbuilt function because the number of fields in the future may increase.
You were looking for following,
%i(a c).map { |x| test.map { |e| e[x] } }
You could use Array#transpose on the pluck result. Which assumes the array represents rows or columns and swaps the representation around.
test.pluck(:a, :c).transpose
#=> [[1, 4], [3, 6]]

How to change values in an array in an efficient way

I am getting the following arrays from external api endpoint.
Input:-
1. [["date", "country_name", "month"], ["2019-02-21", "US", "Jan"]]
2. ["name", "homeAddress", "zipcode"]
Expected Output:-
1. [["Date", "Country Name", "Month"], ["2019-02-21", "US", "Jan"]]
2. ["Name", "Home Address", "Zipcode"]
How can I change the each array in an efficient way in Ruby on Rails?
Update:
Some of the name are different in expected as follows
Input:
["column1", "column2", "date"]
Expected output:
["column3", "column4", "Date"]
How can I get the above output?
Answer:-
Inputs:-
a=['1', '2', '3', '4']
b= {"1"=>"10", "2"=>"20", "3"=>"30"}
Execute:
c=a.map{|i| b[i].nil?? i : b[i] }
Output:-
["10", "20", "30", "4"]
You want to replace '_' with space or bring space when capital letter is encountered within string,
Try following rails methods to do so,
"now_isTheTime".titleize.camelize
=> "Now Is The Time"
ar1 = [["date", "country_name", "month"], ["2019-02-21", "US", "Jan"]]
ar2 = ["name", "homeAddress", "zipcode"]
def formatter(string)
return string if string.length < 3 || string.count("0-9").positive?
string.titleize.camelize
end
ar1.map{ |sub_arr| sub_arr.map(&method(:formatter)) }
ar2.map(&method(:formatter))

make sure two fields in array are unique

I need to make sure the follower_id and followed_id are unique in an array which also includes a third number, called value. All are integers. It is the combination of follower_id and followed_id that needs to be unique not the individual numbers themselves. Here is what I have
Relationship.populate 1..20 do |relationship|
relationship.follower_id = (1..20)
relationship.followed_id = (1..20)
relationship.value = rand(1..5)
end
this would ensure that
1,3,5
1,3,5
2,3,5
1,2,5
would be
1,3,5
2,3,5
1,2,5
Assuming, that the order in pairs is not to be taken into account, and you want to eliminate triples, even having different values, here you go:
a = [[1,3,5], [3,1,5], [2,3,5], [2,3,6], [1,2,5]]
# to count [1,3,5] and [3,1,5] as similar
a.group_by { |(fd,fr,_)| [fd,fr].sort }.values.map &:first
# to count [1,3,5] and [3,1,5] as different
a.group_by { |(fd,fr,_)| [fd,fr] }.values.map &:first
#⇒ [[1,3,5], [3,1,5], [2,3,5], [1,2,5]]
a = [[1,3,5], [1,3,4], [3,1,2], [2,3,2], [2,3,1], [1,2,3]]
If the order of the first two elements of each element of a is important:
a.uniq { |e| e[0,2] }
#=> [[1, 3, 5], [3, 1, 2], [2, 3, 2], [1, 2, 3]]
If the order of the first two elements of each element of a is not important:
require 'set'
a.uniq { |e| Set.new e[0,2] }
#=> [[1, 3, 5], [2, 3, 2], [1, 2, 3]]
Perfect Uniqueness
Here's a solution assuming the order within the triples matters and you want each triple to be perfectly unique. Just use the uniq method on the Array class. It works like this:
[
[1,3,5],
[1,3,5],
[2,3,5],
[1,2,5]
].uniq
#=> [[1, 3, 5], [2, 3, 5], [1, 2, 5]]
Partial Uniqueness
If instead, you only care about the first two being unique, pass the uniq method a block that returns whatever subset you want to be unique. If you only want the first two elements of the triple and can discard duplicates even when the third element is unique, you can just pass it the range 0..1.
[
[1,3,5],
[1,3,5],
[2,3,5],
[1,2,5],
[1,2,6]
].uniq { |triple| triple[0..1] }
#=> [[1, 3, 5], [2, 3, 5], [1, 2, 5]]
Note that the last element, [1,2,6] was discarded even though it ended in 6 because it was considered a duplicate of [1,2,5]. This is because [1,2,5][0..1] #=> [1,2] and [1,2,6][0..1] #=> [1,2].

rails sort of 2 dimensional array does not work

I have a 2d array which is supposed to be a user ranking, based on points. I first init it:
ranked_user = []
Then I do some points calculations and push some stuff into the array:
ranked_user.push([user.id, user.username, user.location, points])
which results in
=> [[8, "Jhonny", "Berlin", 11], [9, "Ben", "Hamburg", 3], [10, "Hugo", "Munich", 6]]
now I want to sort that array based on the 4th value (points) in order to show the ranking.
I've tried two things:
ranked_user.sort_by{|k|k[3]}
and
ranked_user.sort { |a, b| b[3] <=> a[3] }
I expect this:
=> [[9, "Ben", "Hamburg", 3], [10, "Hugo", "Munich", 6], [8, "Jhonny", "Berlin", 11]]
but the array simply is not sorted.
What do I do wrong?
Just to add on to Morgan Laco's answer :
If you do :
ranked_user.sort_by{|k|k[3]}
Then ranked_user would still be unordered. Only the return is ordered.
So in order to change ranked_user, you would have to do either of these :
ranked_user = ranked_user.sort_by{|k|k[3]}
ranked_user.sort_by!{|k|k[3]}
You need to use sort_by! in order to modify the original array.

Resources