1

I have an array of arrays (result of "pluck" usage) in following form:

arr = [[1, 'A1', 'B1'],[2, 'A2', 'B2'],[3, 'A3', 'B3']]

How to get following hash from it?

{1=>[1, 'A1', 'B1'], 2=>[2, 'A2', 'B2'], 3=>[3, 'A3', 'B3']}

I know this form, but surely there is one line form, too

hash = Hash.new

arr.each do |x|
  hash[x[0]] = x
end
7
  • 2
    Personally I like the form you posted just fine - it is probably the most readable and nearly the most compact even if some other incantations might squeeze out a few characters. I'd be inclined to just put it on one line in the {} form arr.each { |x| hash[x[0]] = x} Commented Jun 2, 2021 at 13:53
  • @MichaelBerkowski I'd be inclined to say arr.group_by(&:first) is more compact and more understandable. Commented Jun 2, 2021 at 14:01
  • @engineersmnky Yes I agree, that's a slick implementation. I admit though if I found it in my codebase I'd have to go out to the Array#group_by docs to make sure I knew what it did. Commented Jun 2, 2021 at 14:04
  • 1
    @dawg that will not produce the desired result as it will not retain element sa[0] in the value portion of the Hash Commented Jun 2, 2021 at 14:37
  • 1
    @dawg In my question I mentioned {1=>[1, "A1", "B1"] ... but just because it was simpler for me to implement. You showed quite nice improvement. Commented Jun 2, 2021 at 14:53

2 Answers 2

2

Input

arr = [[1, 'A1', 'B1'],[2, 'A2', 'B2'],[3, 'A3', 'B3']]

Code

p arr.map{|a|[a.first,a]}.to_h

Output

{1=>[1, "A1", "B1"], 2=>[2, "A2", "B2"], 3=>[3, "A3", "B3"]}
Sign up to request clarification or add additional context in comments.

Comments

2

There are few ways I can think.

Use group_by(I personally choose this one), reduce and inject method.

arr = [[1, 'A1', 'B1'],[2, 'A2', 'B2'],[3, 'A3', 'B3']]

arr.reduce({}) { |result, record| result.merge!(record.first => record) }

Or 

arr.inject({}) { |result, record| result.merge!(record.first => record) }

OR

arr.group_by(&:first) # Short and sweet, I think you will pick this up.

6 Comments

The last one is fantastic!
Is original order inside of hash preserved if I use group_by?
arr.group_by(&:first) does not quite get the same result. This collects an array of elements, e.g. the first key/value pair is 1=>[[1, "A1", "B1"]], not 1=>[1, "A1", "B1"] as desired.
You could slap a .transform_values(&:flatten) on the end to get the desired format. However, despite this being "clever", I'd rather opt for a basic solution like this.
I would suggest to use reduce or inject in that case, the complexity will ne O(n), while group_by and then transform_values will be O(2n). So save time and computing power and user reduce.
|

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.