HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

Combining two Arrays of hashes based on a hash key

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
arrayscombininghashtwobasedhasheskey

Problem

I have two arrays of variable lengths: people1 and people2. I want to create an array of arrays where each inner array is a pair of elements from people1 and people2 The pairing should be based on a matching key. I'm using Ruby 2.2.0.

For example, given this input:

people1 = [{ name: :jon, id: 1 }, { name: :jay, id: 3 }, { name: :ray, id: 5 }]
people2 = [{ name: :jon, id: 2 }, { name: :ray, id: 7 }]


I would like this result:

pairs = [
  [{ name: :jon, id: 1 }, { name: :jon, id: 2 }],
  [{ name: :ray, id: 5 }, { name: :ray, id: 7 }]
]


Here's what I came up with:

people1.collect do |p1|
  if p2 = people2.find { |p2| p1[:name] == p2[:name] }
    [p1, p2]
  else
    nil
  end
end.compact


I looked at Array#zip, but it doesn't seem to take a condition. Is there a more idiomatic way to do this?

Solution

First create a hash that maps names to the hashes for one list:

people2_by_name = Hash[people2.map { |h| [h[:name], h] }]


Filter the other list

people1.select { |h| people2_by_name.has_key?(h[:name]) }
       .map { |h| [h, people2_by_name[h[:name]]] }


This will only work properly if there are no duplicate names in each, but it is \$\mathcal{O}(n)\$ in the number of hashes.

Code Snippets

people2_by_name = Hash[people2.map { |h| [h[:name], h] }]
people1.select { |h| people2_by_name.has_key?(h[:name]) }
       .map { |h| [h, people2_by_name[h[:name]]] }

Context

StackExchange Code Review Q#93015, answer score: 4

Revisions (0)

No revisions yet.