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
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.
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.
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.
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!
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]}