I am trying to find out if it is possible to sort a Hash by a specific value if there are multiple values saved to a key.
Example Code:
{
key1: ["Value1", "Value2", "Value3"],
key2: ["Value1", "Value2", "Value3"],
key3: ["Value1", "Value2", "Value3"]
}
I would like to be able to sort by the values in Value2
or by Value1
or any specific value.
If key1
and key2
have the same Value2
they will be returned as:
{Value2: [key1, key2]}
Example:
Value2
representes pets:
- For all the
Value2
that have dog, the key will be saved under a new key, dog. - For all the
Value2
that have cat, it will gather all keys that haveValue2
as cat and group it.
{cat: ["key1", "key2"], dog: ["key3"]}
I am working in Ruby and VScode. I do not want to use an array or nested array because this is not efficient.
Given
{
key1: ["Cop", "dog", "house"],
key2: ["doctor", "cat", "apartment"],
key3: ["Chef", "dog", "house"],
key4: ["Cop", "cat", "apartment"]
}
Expected Output if asked to sort by the values in value2
{
dog: [key1, key3],
cat: [key2, key4]
}
CodePudding user response:
Using #each_with_object
to build up a hash as we iterate over the keys in the original hash.
data = {
key1: ["Cop", "dog", "house"],
key2: ["doctor", "cat", "apartment"],
key3: ["Chef", "dog", "house"],
key4: ["Cop", "cat", "apartment"]
}
data.keys.each_with_object(Hash.new([])) { |k, h|
h[data[k][1]] = [k]
}
# => {"dog"=>[:key1, :key3], "cat"=>[:key2, :key4]}
CodePudding user response:
This doesn't appear to be about sorting, but rather grouping.
It's a matter of iterating through each pair and building a new hash of the matching keys and values.
# A Hash where the default value is a new empty array.
# See https://stackoverflow.com/questions/30367487/creating-a-hash-with-values-as-arrays-and-default-value-as-empty-array
grouped = Hash.new { |h, k| h[k] = [] }
# Iterate through the Hash
h.each { |key, things|
# Get the 2nd thing
thing = things[1]
# Add its key to the thing's group
grouped[thing] << key
}
p grouped
CodePudding user response:
Maybe not the optimal solution but it returns the expected result. The result is basically grouping by value and including the key.
{"cat"=>[:key2, :key4], "dog"=>[:key1, :key3]}
Here's the attempt to solve your challenge:
hash = {
key1: ["Cop", "dog", "house"],
key2: ["doctor", "cat", "apartment"],
key3: ["Chef", "dog", "house"],
key4: ["Cop", "cat", "apartment"]
}
def group_by(animal, hash)
keys = hash.select{|key, value| value[1] == animal }.keys
{animal => keys}
end
a = group_by("cat", hash)
b = group_by("dog", hash)
a.merge(b)
I am sure there is a more "direct" solution.