5

I need to sort an Hash according to order of keys present in other array:

hash = { a: 23, b: 12 }
array = [:b, :a]
required_hash #=> { b: 12, a: 23 } 

Is there any way to do it in single line?

2
  • 1
    What are the values of a and b? Commented Mar 30, 2016 at 7:47
  • 3
    @engineer, since Ruby v.1.9, which came out several years ago, the insertion order of hash keys is maintained. The idea of hash keys being ordered remains controversial, however. Personally, I've made use of that property quite a lot. Commented Mar 30, 2016 at 8:57

4 Answers 4

8
hash = { a: 23, b: 12 }
array = [:b, :a]

array.zip(hash.values_at(*array)).to_h
  #=> {:b=>12, :a=>23}

The steps:

v = hash.values_at(*array)
  #=> [12, 23]
a = array.zip(v) 
  #=> [[:b, 12], [[:a, 23]]
a.to_h
  #=> {:b=>12, :a=>23}
Sign up to request clarification or add additional context in comments.

1 Comment

I personally like @Ilya's answer below
6

You can try something like this:

array = [:b, :a] 
{ a: 23, b: 12 }.sort_by { |k, _| array.index(k) }.to_h
#=> {:b=>12, :a=>23}

Comments

3

If

hash = { a:23, b:12 }
array = [:b, :a]

As a one liner:

Hash[array.map{|e| [e, hash[e]]}]

As for ordering, it was some time ago, when ruby changed the implementation where the hash keys are ordered according to insert order. (Before that there was no guarantee that keys would be sorted one way or another).

4 Comments

Good answer, but I will never understand why people say (sic), "here's a one-liner", followed by a single line of code.
@CarySwoveland Personally, I do it to emphasize that Ruby is succinct and you can write a lot of things into a one liners (in comparison to C#/Java).
Newlines have no meaning in C♯/Java, you can always write any C♯/Java program in one line, no matter how complex, that's not a feature unique to Ruby.
@JörgWMittag Yes, yes, I'm sure you know about www.ioccc.org. To me a one liner is a piece of code that is readable within a reasonable 80-120 chars length.
1

I do not see any sorting, I think essentially you are doing this:

hash = { a:23, b:12 }
array = [:b, :a]
res = {}
array.each { |key| res[key] = hash[key] } && res # `&& res` is just syntax sugar to return result in single line
#=> {:b=>12, :a=>23}

Comments

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.