0

I stuck in a situation, I have an array of array structure how can I make it hash like below:-

Example:

[[378, 1], [144, 1], [144, 1], [144, 3], [144, 7], [144, 6], [144, 8], [144, 8], [809, 1], [809, 1], [809, 8]]  

Convert to:

{378=>[1], 144=>[1,3,7,6,8], 809=>[1,8]}

means take the first element as key and make the second element in another array as value matched to key.

I tried below method but failed in one use case:

raw_hash = arr.group_by { |sub_arr| sub_arr[0] }
modified_hash = {}
raw_hash.each do |k, arr|
   modified_hash[k] = [ arr.flatten.uniq - [ k ] ].flatten
end

failed use-case is if first element and second element both will same then it will make unique and subtract second value

2 Answers 2

4

Just use each_with_object, it is faster and consumes less memory than @mrzasa's approach:

array.each_with_object(Hash.new { |h, k| h[k] = [] }) do |(first, last), m|  
  m[first] |= [last]
end
#=> {378=>[1], 144=>[1, 3, 7, 6, 8], 809=>[1, 8]}

But for the uniqueness the simplest probably would be using Set:

array.each_with_object(Hash.new { |h, k| h[k] = Set.new }) do |(first, last), m|  
  m[first] << last 
end
#=> {378=>#<Set: {1}>, 144=>#<Set: {1, 3, 7, 6, 8}>, 809=>#<Set: {1, 8}>}
Sign up to request clarification or add additional context in comments.

1 Comment

|(first, last), m| nice
3

Group by the first element of the array and then chose the last second elements of the grouped values.

a = [[378, 1], [144, 1], [144, 1], [144, 3], [144, 7], [144, 6], [144, 8], [144, 8], [809, 1], [809, 1], [809, 8]] 
a.group_by(&:first).map{|k, v| [k, v.map(&:last)]}.to_h
# => {378=>[1], 144=>[1, 1, 3, 7, 6, 8, 8], 809=>[1, 1, 8]}

EDIT:

If you want to have a unique values, add uniq to the map that collects them:

a.group_by(&:first).map{|k, v| [k, v.map(&:last).uniq]}.to_h
#=> {378=>[1], 144=>[1, 3, 7, 6, 8], 809=>[1, 8]}

7 Comments

Updated, see now.
This solution is ok for the instance from the question, but extremely slow and inefficient if array is quite big.
How big is quite big to make the difference significant?
@mrzasa you can perform benchmarking, it doesn't matter actually :) If we can do something obviously faster and consume less memory why just don't do it? :)
chaining maps & group_by in opposition to each and mutating arrays (I know that too many maps causes GC overhead).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.