Ruby: comparing two Arrays of Hashes and mapping one to the other Can you help me to optimize my code for the following problem: 

An array of hashes named expected_tasks has tasks. Each task has a user that has to execute an action and contains fields. 
The expected_tasks are related to the actual_tasks. 
We want to execute the expected_task[action] on the actual_task["id]". 
Therefor want to be able to select the actual_task["id"] where all the fields have the same value. 

In the end this means that the expected_tasks[0] matches to the actual_tasks[0] because their fields are exactly the same. When their is a match, we can use actual_task["id"]. 

This is what the data looks like: 

#the fields_to_check is an extraction of the keys of the expected_tasks minus user and action
fields_to_check = [ 'field_to_check_1', 'field_to_check_2' ] 

expected_tasks = [{ 'user' =&gt; 'user', 
                     'action' =&gt; 'action_y', 
                     'field_to_check_1' =&gt; 'value_a', 
                     'field_to_check_2' =&gt; 'value_a' },{
                     'user' =&gt; 'user', 
                     'action' =&gt; 'action_x', 
                     'field_to_check_1' =&gt; 'value_b', 
                     'field_to_check_2' =&gt; 'value_b'} ]

sparse_actual_subtasks = [{ 'id' =&gt; '1' , 
                     'field_to_check_1' =&gt; 'value_b', 
                     'field_to_check_2' =&gt; 'value_b' },{
                     'id' =&gt; '2' , 
                     'field_to_check_1' =&gt; 'value_a', 
                     'field_to_check_2' =&gt; 'value_a' }]


The piece of code to map the id from actual_task to the right action + user from the expected_task: 

expected_tasks.each do |expected_task|

  mapped_tasks = []

  actual_task = sparse_actual_subtasks.find do |actual_task|
    fields_to_check.all? do |field| 
    expected_task[field] == actual_task[field] 
    end
  end

  #map action and user to task with id 
  actual_task['action'] = expected_task['action']
  actual_task['user'] = expected_task['user']
  mapped_tasks &lt;&lt; actual_task

  puts mapped_tasks

end
def mapped_tasks(expected, subtasks, fields)
  fields_match = -&gt;(t1, t2) {fields.all? {|f| t1[f] == t2[f]}}
  expected.map do |e| 
    subtask = subtasks.find {|s| fields_match.(e,s)}
    subtask ? e.merge(subtask) : nil
  end.compact
end


should do the same as your original.


use merge rather than explicitly adding each field you want
create a lambda to name the condition of "all relevant fields matching".  this makes the loop within which it is called more readable.
rather than procedurally declaring an array and adding items to it, simply use map to chang all the expected items.  the ones that don't match are changed to nil, and we remove them at the end using compact


notes on the original code:


the data structures that we're assuming exist seem ill-fitted to the problem.  if they're within your control, consider simplifying them.  this should make the solution to the problem here more natural
avoid extraneous information in your variable names.  it gives the illusion of greater clarity but in fact makes the code harder to read at a glance.  eg fields is a clearer name than fields_to_check