Iterate Through Array of Hashes in Ruby

How to iterate through an array of hashes in ruby

In newer versions of Ruby (not sure when it was introduced, probably around ruby 2.0-ish which is when I believe keyword arguments were introduced), you can do:

people.each do |salary:,**|
puts salary
end

where ** takes all the keyword arguments that you don't name and swallows them (ie, the first_name and job_title keys in the hash). If that isn't something that your ruby version allows, you'll need to just store the entire hash in the variable:

people.each do |person|
puts person[:salary]
end

Ruby iterate over an array of hashes

There is no need for the second loop. The following does what you want:

keys = stack[:all].map(&:to_sym)
keys.each do |key|
stack[key][:COUNT] = stack[key][:MAX_SIZE] * 2
end

In the above code-block stack[:all] will return an array of keys as strings, .map(&:to_sym) will convert each string in the resulting array into a symbol.


Another way to achieve the same result would be to use either fetch_values or values_at to retrieve an array of values belonging to the provided keys. The difference being that fetch_values raises an exception if a key is missing while values_at returns nil for that key.

fruits = stack.fetch_values(*stack[:all].map(&:to_sym))
fruits.each do |fruit|
fruit[:COUNT] = fruit[:MAX_SIZE] * 2
end

If you are wondering why there is a * before stack[:all].map(&:to_sym), this is to convert the array into individual arguments. In this context * is called the spat operator.

How to iterate over an array of hashes in Ruby and return all of the values of a specific key in a string

You can use Enumerable#map for this:

p foods.map { |f| f[:name] }

The code you tried to use did not produce any output or create any objects, and it was not necessary to use a second loop to access a single element of a hash.

Loop through array of hash with a key containing an array

A simple approach is to just iterate both, array and product ids:

array.each do |hash|
hash[:product_ids].each do |product_id|
StoreExcludedProduct.create(
store_id: hash[:store_id],
product_id: product_id
)
end
end

You can wrap the above code in a transaction call to avoid having separate transactions for each create, i.e.:

StoreExcludedProduct.transaction do
array.each do |hash|
# ...
end
end

This also makes your code run in an all-or-nothing way.

Another option is insert_all which can insert multiple records at once. In order to use it, you have to first build an array of attributes for each record, i.e. you have to split the product ids. This works a lot like the above code:

attributes = array.flat_map do |hash|
hash[:products_ids].map do |product_id|
{ store_id: hash[:store_id], product_id: product_id }
end
end
#=> [
# {:store_id=>5, :product_id=>1},
# {:store_id=>5, :product_id=>4},
# {:store_id=>5, :product_id=>19},
# {:store_id=>5, :product_id=>40},
# {:store_id=>13, :product_id=>2},
# #...
# ]

which can be passed to insert_all:

StoreExcludedProduct.insert_all(attributes)

Note that this performs a raw SQL query without instantiating any models or running any callbacks or validations.

How to iterate over an array of hashes in Ruby to compare each member with the following members in the array?

Note that you're not using "i" inside your loop, which looks like a bug. Also, your index "j+1" is going off the end of the array, resulting in accessing the nil element. Actually, even "j" goes off the end of the array. Arrays are accessed from 0...length-1, whereas "0..data.length" will access the element at index data.length. I'm guessing you mean something more like:

for i in 0..data.length-2
for j in i+1..data.length-1
output = (data[i].keys & data[j].keys).select { |k| data[i][k] == data[j][k] }
end
end

Ruby - Iterate over array of hashes and sum/compact the values of duplicate keys

What's wrong with a straightforward iteration through all the items?

arr = [{"94838"=>30.0}, {"94916"=>2.0}, {"94916"=>10.0}]

hsh = Hash.new(0) # Default value for each key is zero

# For each hash in arr, iterate through each key/value pair and
# increment the destination total associated with the key by the
# current value. Can use increment because of the zero default.
arr.each { |h| h.each { |k, v| hsh[k] += v } }
p hsh # Produces {"94838"=>30.0, "94916"=>12.0} as desired

Iterate an array of hashes

For your corrected data format:

@locations = { "cities"=>[
{ "longitude"=>-77.2497049,
"latitude"=>38.6581722,
"country"=>"United States",
"city"=>"Woodbridge, VA"},
{ "longitude"=>-122.697236,
"latitude"=>58.8050174,
"country"=>"Canada",
"city"=>"Fort Nelson, BC" }] }

@locations["cities"].each { |h| puts h["city"] }
Woodbridge, VA
Fort Nelson, BC

or to save in an array:

@locations["cities"].each_with_object([]) { |h,a| a << h["city"] }
#=> ["Woodbridge, VA", "Fort Nelson, BC"]

How can I iterate over an array of hashes and form new one

You can use map which will iterate through the elements in an array and return a new array:

companies["items"].map do |c| 
{
title: c['title'],
company_number: c['company_number']
}
end
=> [
{:title=>"First company", :company_number=>"10471071323"},
{:title=>"Second company", :company_number=>"1047107132"}
]


Related Topics



Leave a reply



Submit