ericalli
ericalli

Reputation: 1233

Ruby compare and match array to hash of arrays

I've defined a static hash of arrays with a master list of amenities organized into categories like so:

amenities = {
    "food" => [
        "Bar/lounge",
        "Restaurant",
        "Room service"
    ],
    "transportation" => [
        "Shuttle",
        "Ski shuttle",
        "Airport transportation"

    ],
    "facilities" => [
        "Fitness facilities",
        "Indoor pool",
        "Business center",
    ]
}

and I'm working with an API that returns a list of amenities in a flat, uncategorized array like this:

response = [
    "Bar/lounge",
    "Shuttle",
    "Ski shuttle",
    "Indoor pool"
]

Is there a straight forward way to iterate over and compare/match the response list to the master list to find what categories the response amenties belong to? With the examples above, the ideal result would be:

result = {
    "food" => [
        "Bar/lounge"
    ],
    "transportation" => [
        "Shuttle",
        "Ski shuttle"

    ],
    "facilities" => [
        "Indoor pool"
    ]
}

So only the response list is organized in the a resulting hash, with the amenties organized by category as defined in the master list.

Any help would be much appreciated!

Upvotes: 1

Views: 75

Answers (3)

Cary Swoveland
Cary Swoveland

Reputation: 110675

I'd do it like this:

amenities.merge(amenities) { |*_,a| a & response }
  #=> {"food"=>["Bar/lounge"],
  #    "transportation"=>["Shuttle", "Ski shuttle"],
  #    "facilities"=>["Indoor pool"]}

Upvotes: 3

Arup Rakshit
Arup Rakshit

Reputation: 118271

amenities = {
  "food" => [
    "Bar/lounge",
    "Restaurant",
    "Room service"
  ],
  "transportation" => [
    "Shuttle",
    "Ski shuttle",
    "Airport transportation"

  ],
  "facilities" => [
    "Fitness facilities",
    "Indoor pool",
    "Business center",
  ]
}

response = [
  "Bar/lounge",
  "Shuttle",
  "Ski shuttle",
  "Indoor pool"
]

result = response.each_with_object({}) do |item, hash|
  search = amenities.find { |_,values| values.include?(item) }
  (hash[search.first] ||= []) << item unless search.nil?
end

puts result
# => {"food"=>["Bar/lounge"],
#     "transportation"=>["Shuttle", "Ski shuttle"],
#     "facilities"=>["Indoor pool"]}

Upvotes: 1

Surya
Surya

Reputation: 15992

One way could be:

result = {}
amenities.each do |key, values|
  result[key] = values.select{|v| response.include?(v) }
end
p result
#=> {
      "food"=>["Bar/lounge"], 
      "transportation"=>["Shuttle", "Ski shuttle"], 
      "facilities"=>["Indoor pool"]
    }

or:

p amenities.each_with_object({}) { |(key, values), result| 
  result[key] = values.select{|v| response.include?(v) } 
}
#=> {
      "food"=>["Bar/lounge"], 
      "transportation"=>["Shuttle", "Ski shuttle"], 
      "facilities"=>["Indoor pool"]
    }

or:

p amenities.inject({}) { |result, (key, values)|
     result[key] = values.select{|v| response.include?(v) }; result
   }
#=> {
      "food"=>["Bar/lounge"], 
      "transportation"=>["Shuttle", "Ski shuttle"], 
      "facilities"=>["Indoor pool"]
    }

Upvotes: 1

Related Questions