Remove subarrays having duplicate value at the same index - ruby-on-rails

I have a multi-dimensional array that contains a lot of information about various objects. I'm looking to remove all but the first instance of arrays that contain similar information:
multi_array = [
["Nissan", "Altima", "tan", "2016", "80000"],
["Ford", "F-150", "silver", "2012", "120000"],
["Nissan", "Altima", "red", "2009", "50000"],
["Audi", "A4", "blue", "2014", "30000"]
]
In the above example I want to remove any of the subarrays that have the instance of "Altima" in it so that result would be:
fixed_multi_array = [
["Nissan", "Altima", "tan", "2016", "80000"],
["Ford", "F-150", "silver", "2012", "120000"],
["Audi", "A4", "blue", "2014", "30000"]
]
What's the fastest way to do this in ruby (or Ruby on Rails)?
Update:
Should have clarified, I'm looking to de-duplicate based on a value that's always in the same position of the sub-arrays. So, in example above I'm always looking to de-dupe only on value in position 1 of the sub-arrays.

You can use uniq:
fixed_multi_array = multi_array.uniq{|x| x[1]}
Demonstration

Here is one more way to do this:
multi_array.group_by {|i| i[1]}.values.map(&:first)

Related

i want to get key value of array in ruby

In a .rb file I am using result = JSON.parse(res.body)['data']['results'] and get
[
{"suggestion":"Lineman","id":"49.10526"},
{"suggestion":"Linguist","id":"27.10195"},
{"suggestion":"Librarian","id":"25.47"},
{"suggestion":"Lifeguard","id":"33.39"},
{"suggestion":"Line Cook","id":"35.30125"},
{"suggestion":"Life Coach","id":"21.209"},
{"suggestion":"Life Guard","id":"33.1001"}
]
now I want an array like
[
"Lineman",
"Linguist",
"Librarian",
"Lifeguard",
"Line Cook",
"Life Coach",
"Life Guard"
]
What should I apply to JSON.parse(res.body)['data']['results']?
You can use Enumerable#map:
other_result = result.map { |val| val['suggestion'] }
it returns a new array with results of applying the block to initial array elements
Try this:
suggestions = result.pluck(:suggestion)
# ["Lineman", "Linguist", "Librarian", "Lifeguard", "Line Cook", "Life Coach", "Life Guard"]
This plucks all the suggestion values and returns them as an array.

rails array of hashes calculate one column

I have an array and it has many columns and I want to change one value of my one column.
My array is:
[
{
id: 1,
Districts: "Lakhisarai",
Area: 15.87,
Production: 67.77,
Productivity: 4271,
Year: 2015,
Area_Colour: "Red",
Production_Colour: "Orange",
Productivity_Colour: "Dark_Green",
created_at: "2018-07-24T11:24:13.000Z",
updated_at: "2018-07-24T11:24:13.000Z"
},
{
id: 29,
Districts: "Begusarai",
Area: 18.53,
Production: 29.35,
Productivity: 1584,
Year: 2015,
Area_Colour: "Red",
Production_Colour: "Red",
Productivity_Colour: "Orange",
created_at: "2018-07-24T11:24:13.000Z",
updated_at: "2018-07-24T11:24:13.000Z"
},
...
]
This is my sample array and I want my Productivity to be divided by 100 for that I am using one empty array and pushing these hashes to my array like:
j = []
b.map do |k|
if k.Productivity
u = k.Productivity/100
j.push({id: k.id, Productivity: u })
else
j.push({id: k.id, Productivity: k.Productivity })
end
Is there any simple way where I can generate this kind of array and reflect my changes to to one column. Is there any way where I don't need to push name of column one by one in push method.
I want to generate exact same array with one modification in productivity
let's say your array is e, then:
e.each { |item| item[:Productivity] = item[:Productivity]/100}
Example:
e = [{p: 12, d: 13}, {p:14, d:70}]
e.each { |item| item[:p] = item[:p]/10}
output: [{:p=>1, :d=>13}, {:p=>1, :d=>70}]
You could take help of map method here to create a new array from your original array, but with the mentioned changes.
ary.map do |elem|
h = elem.slice(:id)
h[:productivity] = elem[:Productivity] / 100 if elem[:Productivity]
h
end
=> [{:id=>1, :productivity=>42}, {:id=>29, :productivity=>15}]
Note, Hash#slice returns a new hash with only the key-value pairs for the keys passed in argument e.g. here, it returns { id: 1 } for first element.
Also, we are assigning the calculated productivity to the output only when it is set on original hash. Hence, the if condition there.

match key of hash and then fetch values accordingly in ruby

I have included the given code:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = params[:test] #I get "1,3,7"
I get this, now please guide me how to match keys with #amaze and accordingly fetch its values from #classes i.e USA, France, Delhi.
Since #amaze is just a String, lets first convert it in Array so its easy to enumerate:
#amaze = "1,3,7"
#amaze = #amaze.split(",")
# => ["1", "3", "7"]
Now, since you have all keys extract all values:
#amaze.map { |i| #classes[i.to_i] }
# => ["USA", "France", "Delhi"]
Split #amaze by , and get an array of keys, convert them into Integer, then select only those key/value pairs which key is into this array of keys. Something like this:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = "1,3,7" #I get "1,3,7"
arr = #amaze.split(',').map(&:to_i)
p #classes.select{|el| arr.include? el}
Result:
#> {1=>"USA", 3=>"France", 7=>"Delhi"}
If you want values only use .values:
p #classes.select{|el| arr.include? el}.values
Result:
#> ["USA", "France", "Delhi"]
For what(seemingly) you are asking, the below line will do it:
#amaze.split(",").each { |i| p #classes[i.to_i] }
# If #amaza = "1,3,7", above line will output:
# => "USA"
# "France"
# "UK"
This should work well for you:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = params[:test].split(",").map(&:to_i)
#classes.values_at(*#amaze)
#=> ["USA", "France", "Delhi"]
Hash#values_at accepts an indefinite number of keys and returns their values as an array. The * (splat) operator explodes the array so this call actually becomes #classes.values_at(1,3,7) Docs
Might also want to add a compact to the end in the event a key does not exist. e.g
#amaze = params[:test].split(",").map(&:to_i) # Asssume this returns [1,3,7,9]
#classes.values_at(*#amaze)
#=> ["USA", "France", "Delhi",nil]
#classes.values_at(*#amaze).compact
#=> ["USA", "France", "Delhi"]
I think a clearer understanding of hashes would help you out here.
A Hash is a data structure that is a list of key-value pairs. For example, the following is a Hash object of key-value pairs (your example):
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
If you want to extract a value from #classes, you need to pass the key of the value you want. If we wanted "USA" we would pass the key of 1 to #classes. If we wanted "France", we would pass it the key of 3:
#classes[1] would return "USA" and #classes[3] would return "France".
It's not clear what data structure #amaze is according to your question, but let's say it's the string "1, 3, 7" which we can split to create an array [1, 3, 7].
You could iterate over the array to get each of the values from #classes:
#amaze.split(",").map(&:to_i).each do |key|
puts #classes[key]
end
That would print out each of the corresponding values to keys in #classes.

Ruby deep_merge on an array of hashes

I want to merge an attribute on hashes nested inside an array, which is nested inside a hash.
ball = {
name: "Hugh",
colors: [
{name: "Blue"},
{name: "Red"}
]
}
I tried to use deep merge, but I think it only supports merging into a nested hash, not an array of hashes.
balls.deep_merge(size: "small")
Output:
ball = {
name: "Hugh",
colors: [
{name: "Blue"},
{name: "Red"}
],
size: "small"
}
Expected output.
ball = {
name: "Hugh",
colors: [
{name: "Blue", size: "small"},
{name: "Red", size: "small"}
]
}
You can iterate over the array (depending on how abstract you need it to be).
ball[:colors].each {|c| c[:size] = "small"}
Or, assuming you have a "balls" array, this would work for mass assignment.
balls.each {|ball| ball[:colors].each {|c| c[:size] = "small"} }
There is nothing that can do this automagically, I'm afraid. There is no way for a program to know that { size: "small" } is meant to go into each hash of the colors key and not in any other.
But you've got a good start here formulated the question almost as a unit test, so I have no doubt you can find a manual way to do this with TDD!

How can I get the number of instances of a value in a Rails array?

Say I have an array like this:
["white", "red", "blue", "red", "white", "green", "red", "blue", "white", "orange"]
I want to go through the array and create a new array containing each individual color and the amount of times it appeared in the original array.
So, in the new array it would report that "white" appeared 3 times, "blue" appeared 2 times and so on...
How should I go about doing this?
better return a hash...
def arr_times(arr)
arr.inject(Hash.new(0)) { |h,n| h[n] += 1; h }
end
counts = Hash.new(0)
colors.each do |color|
counts[color] += 1
end
result = {}
hash = array.group_by{|item| item}.each{|key, values| result[key] = values.size}
p result
I see you tagged the question with ruby-on-rails.
If this is a database model/column (e.g., User model with color attribute) you should be doing the computation in the DB:
User.count(:all,:group=>:color).sort_by {|arr| -arr[1]}

Resources