简体   繁体   中英

Rails merging two arrays of hashes?

I'm having a hard time grasping the logic I'd need to merge two arrays of hashes, It seems I've asked t his question a while back in sort of a different way, I've also tried a few other things like the answers offered here: merging arrays of hashes

Any sort of help understanding this would be really helpful to me.

Say I have the following array, and this is output from the method itself, so you can imagine those :timestamp s to be Time objects

[
  {:timestamp=>2011-12-19 00:00:00 UTC},
  {:timestamp=>2011-12-19 01:00:00 UTC},
  {:timestamp=>2011-12-19 02:00:00 UTC},
  {:timestamp=>2011-12-19 03:00:00 UTC},
  {:timestamp=>2011-12-19 04:00:00 UTC},
  {:timestamp=>2011-12-19 05:00:00 UTC}
]

And then an additional array like this, each of which has another value (but sometimes may have a bunch more values besides :count )

[
  {:timestamp=>2011-12-19 02:00:00 UTC, :count=>5},
  {:timestamp=>2011-12-19 04:00:00 UTC, :count=>21}
]

And result in something like this:

[
  {:timestamp=>2011-12-19 00:00:00 UTC},
  {:timestamp=>2011-12-19 01:00:00 UTC},
  {:timestamp=>2011-12-19 02:00:00 UTC, :count=>5},
  {:timestamp=>2011-12-19 03:00:00 UTC},
  {:timestamp=>2011-12-19 04:00:00 UTC, :count=>21},
  {:timestamp=>2011-12-19 05:00:00 UTC}
]

Again, thanks for your help, I'm not sure why I just can't figure out the proper design pattern for this.

看起来你首先按时间戳分组,然后合并值:

(a1+a2).group_by{|h| h[:timestamp]}.map{|k,v| v.reduce(:merge)}
a = [
  {:timestamp=>'2011-12-19 00:00:00 UTC'},
  {:timestamp=>'2011-12-19 01:00:00 UTC'},
  {:timestamp=>'2011-12-19 02:00:00 UTC'},
  {:timestamp=>'2011-12-19 03:00:00 UTC'},
  {:timestamp=>'2011-12-19 04:00:00 UTC'},
  {:timestamp=>'2011-12-19 05:00:00 UTC'}
]

b = [
  {:timestamp=>'2011-12-19 02:00:00 UTC', :count=>5},
  {:timestamp=>'2011-12-19 04:00:00 UTC', :count=>21}
]

result = a.inject([]) do |memo, v|
  if match = b.detect { |w| (w.to_a & v.to_a).any? }
    memo << match.merge(v)
  else
    memo << v
  end
end

p result

Since you are using the :timestamp attribute of each hash as its "key", it is easy if you actually convert the arrays into hashes with the :timestamp property as the key:

h1 = Hash[a1.map{|h| [h[:timestamp], h]}]
h2 = Hash[a2.map{|h| [h[:timestamp], h]}]

Then, what you want reduces to simply merge -ing the two hashes (and getting away with the keys that were added):

p h1.merge(h2).values
# => [
#  {:timestamp=>"2011-12-19 00:00:00 UTC"},
#  {:timestamp=>"2011-12-19 01:00:00 UTC"},
#  {:timestamp=>"2011-12-19 02:00:00 UTC", :count=>5},
#  {:timestamp=>"2011-12-19 03:00:00 UTC"},
#  {:timestamp=>"2011-12-19 04:00:00 UTC", :count=>21},
#  {:timestamp=>"2011-12-19 05:00:00 UTC"}
#]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM