Reputation: 5545
I need a Ruby function that takes a hash as input (keys are Symbols and values are Arrays of Numerics) and returns the list of keys whose associated Arrays have the same first value.
Here is an example :
h={
:k1 => [2,3,5,12],
:k2 => [9,5,6,10],
:k3 => [2,4,5, 8],
}
f(h) # should return [[:k1,:k3]]
...because 2 appears as the same value in the two arrays associated with :k1 and :k3. The return Object is an array of array (because, several groups of keys can have the same array first values).
So far, I just grouped the arrays themselves :
def f(h)
h.values.group_by{|ary| ary.first}
end
# returns {2=>[[2, 3, 5, 12], [2, 4, 5, 8]], 9=>[[9, 5, 6, 10]]}
Upvotes: 0
Views: 310
Reputation: 1
This is for list of array.
array1 = [1,2,3,4,5,6,7,8,9,10,11,12,13]
myarray = []
myfinalarray = []
array1.each do |item|
if myarray.size == 3
myfinalarray.push(myarray)
myarray = []
end
myarray.push(item)
end
myfinalarray.push(myarray)
puts "group of 3 items of an array #{myfinalarray}"
Upvotes: -2
Reputation: 1023
Why not just use group_by
as the title of your question suggests:
h2 = h.group_by { |k, v| v.first }
This gives you something like this:
{2=>[[:k1, [2, 3, 5, 12]], [:k3, [2, 4, 5, 8]]], 9=>[[:k2, [9, 5, 6, 10]]]}
You can then use this for further processing. Just want the keys?
h3 = h2.values.map { |v| v.map(&:first) }
Only want those with more than one key?
h3.reject { |v| v.length < 2 }
Or on h2
directly:
h2.reject { |k, v| v.length < 2 }
Upvotes: 2
Reputation: 820
I came up with this ugly thing:
h.inject({}) do |memo, (key, array)|
memo[array[0]] ||= []
memo[array[0]] << key
memo
end.detect do |(key, values)|
values.size > 1
end.last
It basically remaps the hash in the form of:
{first_item_in_array => keys_that_contain_it}
Or, in our case:
{2=>[:k1, :k3]}
Then it just detects the first pair that has more than one match and returns it:
[:k1, :k3]
Hope that helps!
Upvotes: 1
Reputation: 2869
Maybe you can use something like this
def get_same_first_value(h)
h.each_with_object(Hash.new { |k, v| k[v] = [] }) do |(sym, arr), exp|
exp[arr.min] << sym
end.select { |k, v| v.size != 1 }.values
end
h = {
:k1 => [2, 3, 5, 12],
:k2 => [9, 5, 6, 10],
:k3 => [2, 4, 5, 8],
}
get_same_first_value(h)
# => [[:k1, :k3]]
Upvotes: 0