4

I have an array of hashes:

[{:foo => 1, :bar => 2}, {:foo => 2, :bar => 4} ...]

And an array of integers:

[3, 6]

I want combine the values from the integer array and the hashes to end up with something like:

[{:foo => 1, :bar => 2, :baz => 3}, {:foo => 2, :bar => 4, :baz => 6}]

I am currently doing this:

myArrayOfHashes.each_with_index |myHash, index|
    myHash[:baz] = myArrayOfIntegers[index]
end

Is that the right approach?

I was imagining a more functional approach where I iterate over both arrays simultaneously, like something using zip + map.

5
  • It's not necessary to repeatedly specify you want to do this with Ruby. The tags you set will tell us the language and features or libraries. Commented Jun 21, 2013 at 7:02
  • Yeah, good call @theTinMan. Just never sure if favorite tags are used by the person who could answer. But, noted for the future. Commented Jun 21, 2013 at 7:06
  • 1
    If someone tries to answer who hasn't paid attention to the tags, the odds are really good they'll get plenty of down-votes for not having paid attention. They won't repeat that. Commented Jun 21, 2013 at 7:08
  • 1
    Your current implementation looks good enough for me already Commented Jun 21, 2013 at 7:09
  • @JanDvorak +1 for efficiency and less memory consumption. Commented Jun 21, 2013 at 7:22

3 Answers 3

6

Try:

require 'pp'

ary_of_hashes = [{:foo => 1, :bar => 2}, {:foo => 2, :bar => 4}]
[3, 6].zip(ary_of_hashes).each do |i, h|
  h[:baz] = i
end

pp ary_of_hashes

Which results in:

[{:foo=>1, :bar=>2, :baz=>3}, {:foo=>2, :bar=>4, :baz=>6}]

zip is a good tool for this, but map won't really buy much, at least nothing that you can't do as easily with each in this case.

Also, don't name variables using CamelCase like myArrayOfHashes, instead use snake_case, like ary_of_hashes. We use CamelCase for class names. Technically we can used mixed case for variables, but by convention we don't do that.

And, it's possible to use each_with_index, but it results in awkward code, because it forces you to use an index into [3, 6]. Let zip join the respective elements of both arrays and you'll have everything you need to massage the hash.

Sign up to request clarification or add additional context in comments.

3 Comments

Try ri Kernel.pp from the command-line, or check ruby-doc.org/stdlib-2.0/libdoc/pp/rdoc/index.html
Very good. I figured I could use zip here and do exactly this, not sure what mistake I was making when I tried it earlier.
Yeah, I also follow those conventions when actually writing code. I am not sure why I decided to write my sample like that - I guess too much scala recently.
6

map is useful when you want to leave the original objects intact:

a = [{:foo => 1, :bar => 2}, {:foo => 2, :bar => 4}]
b = [3,6]
a.zip(b).map { |h, i| h.merge(baz: i) }
# => [{:foo=>1, :bar=>2, :baz=>3}, {:foo=>2, :bar=>4, :baz=>6}]
a.inspect
# => [{:foo=>1, :bar=>2}, {:foo=>2, :bar=>4}]

2 Comments

According to the code sample in the question, it should be a.zip(b).each {|h, i| h.update(baz: i)} rather than creating a new Hash and leaving a unchanged.
I may have been over-reaching with looking to use map since it looks like it might not be necessary. + 1 still though.
3
array_of_hashes.each { |hash| hash.update baz: array_of_integers.shift }

7 Comments

Good (+1) but it destroys array_of_integers.
Caution with array_of_integers.shift. It'll be destructive.
Right, to preserve the array of integers, array_of_integers.dup should be called first.
@BorisStitnicky how is mine? :)
@OMG: Your option is legitimate, but voting mistakes happen. But if you really want to contribute, don't you happen to know the answer to this question of mine? I thought it was just a simple JavaScript question, but it's already up for 2 days, and nothing.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.