learning_to_swim learning_to_swim - 2 months ago 6
Ruby Question

Add missing hashes from one Array into another

I have two ruby Arrays. The source_array contains all my source data in form of hashes. I have a user_array that contains a subset of data that a user has selected. I need to merge/combine the two arrays to form a new result_array keeping all the hashes from the user_array and adding those hashes from the source_array that does not exist in the user_array.

Source Array:

source_array = [
{:category=>"truck", :make=>"ford", :model=>"F150", :notes=>""},
{:category=>"truck", :make=>"ford", :model=>"F250", :notes=>""},
{:category=>"truck", :make=>"ford", :model=>"F350", :notes=>""},
{:category=>"truck", :make=>"chevy", :model=>"Silverado 1500", :notes=>""}
]


Target Array:

target_array = [
{:category=>"truck", :make=>"ford", :model=>"F150", :notes=>"Mileage 290 miles for a full tank of gas. Shortlist for now."}
]


Result Array:

result_array = [
{:category=>"truck", :make=>"ford", :model=>"F150", :notes=>""},
{:category=>"truck", :make=>"ford", :model=>"F250", :notes=>""},
{:category=>"truck", :make=>"ford", :model=>"F350", :notes=>""},
{:category=>"truck", :make=>"ford", :model=>"F150", :notes=>"Mileage 290 miles for a full tank of gas. Shortlist for now."}
]


I appreciate any help you can provide!

Answer

We are given

source_arr =
[ 
  {:category=>"truck", :make=>"ford",  :model=>"F150", :notes=>""}, 
  {:category=>"truck", :make=>"ford",  :model=>"F250", :notes=>""}, 
  {:category=>"truck", :make=>"ford",  :model=>"F350", :notes=>""},
  {:category=>"truck", :make=>"chevy", :model=>"Silverado 1500", :notes=>""}
]

target_arr =
[ 
  {:category=>"truck", :make=>"ford", :model=>"F150",
   :notes=>"Mileage 290 miles for a full tank of gas. Shortlist for now."},
  {:category=>"truck", :make=>"ford",  :model=>"F350", :notes=>"what a beast!"}
]

First construct a hash with the keys that are to be matched.

target_hashes = target_arr.map { |h| h.reject { |k,_| k == :notes } }
  #=> [{:category=>"truck", :make=>"ford", :model=>"F150"},
  #    {:category=>"truck", :make=>"ford", :model=>"F350"}]

Next construct an array that contains all the hashes in source_arr that do not match all the keys of hashes in target_hashes.

sources_to_add = source_arr.reject { |h|
  target_hashes.include?(h.reject {|k,_| k == :notes }) }
  #=> [{:category=>"truck", :make=>"ford", :model=>"F250", :notes=>""},
  #    {:category=>"truck", :make=>"chevy", :model=>"Silverado 1500", :notes=>""}]

Now construct the desired array.

target_arr + sources_to_add
  #=> [{:category=>"truck", :make=>"ford", :model=>"F150",
  #     :notes=>"Mileage 290 miles for a full tank of gas. Shortlist for now."},
  #    {:category=>"truck", :make=>"ford", :model=>"F350",
  #     :notes=>"what a beast!"},
  #    {:category=>"truck", :make=>"ford", :model=>"F250", :notes=>""},
  #    {:category=>"truck", :make=>"chevy", :model=>"Silverado 1500",
  #     :notes=>""}]

if you don't want to modify target_arr or

target_arr += sources_to_add

if you do.