2

I have the following:

article_results.keys do |key|
  article_results[key].map! do |a|
    a[:filename] = c.filename
    a[:sitename] = c.site_name
    a
  end
end

As I want to add to each element of each array within the hash dynamically, but for some reason a[:filename] and a[:sitename] are blank when they are used.

So I want to know if I should be using .each instead. Also I guess I'd like to know what's the main difference since they both can be used for side-effects.

I'm adding this as an extra fyi, I'm using ruby 1.8.7 so it would be nice to know how it differs between versions (1.8.7 - 1.9+) as well.

P.s. I know what the difference between .each and .map is, I'm asking specifically about .map!.

1 Answer 1

1

#map has a bit different semantics for hashes than it has for arrays (and i think it's not very consistent between versions of ruby). in general if you are looking for an array as a result of some operation - #map is your friend, however if you want hash as a result of some operation - you're better off with #reduce:

article_results.reduce({}) do |hash, (key, value)|
  hash.merge(key => value.merge(filename: c.filename,
                                sitename: c.sitename))
end

alternatively if you don't care how "functional" your code is, you can use #each:

article_results.each do |key, value|
  article_results[key].merge!(filename: c.filename,
                              sitename: c.sitename)
end
Sign up to request clarification or add additional context in comments.

5 Comments

I keep forgetting there's a difference between 1.8.7 (which I'm currently forced to use) and 1.9+, I'll add that to the op. reduce looks like inject, is that the same thing? Also, article_results is a hash of arrays of objects with hash like setters & getters to add extra data.
correct, reduce is alias to inject (or vice versa). it's just a matter of coherent naming - map goes with reduce, inject goes with collect. from code in your question it looks like artice_results is hash of hashes (or objects that behave like hashes) so merge! should work on them. if it doesn't - just use []= directly.
actually if article_results is hash of arrays then your map! code is correct and you should make sure c.filename is valid. and ofc .keys doesn't take a block, must be .keys.each
ah, it's probably becuase I forgot to do a .each still, doing .each on the hash should be slightly faster as it doesn't have to generate the array of keys each time.
it is a micro-optimization. code quality and clarity should be your top priority.

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.