Impossible to sort a hash by key?

Hi everyone!

is it impossible to sort a hash by key?

I have a hash like {"plums"=>3, "bananas"=>4, "apples"=>6}

And what i want is {"apples" => 6, "bananas" => 4, "plums" => 3}

Hash#sort returns an array. So i've tried this:

class Hash
  def sort_by_key
    array = self.sort
    # the array is sorted!
    array.inject({}) do |hash, value|
      hash[value.first] = value.last
      hash
    end
  end
end

But the result is {"plums"=>3, "bananas"=>4, "apples"=>6}!

So - is it impossible to sort a hash by key?

Oliver.

···

--
Posted via http://www.ruby-forum.com/.

Oliver Katzer wrote:

is it impossible to sort a hash by key?

Yes, because hashes are un-ordered containers.

Look up OrderedHash on the RAA for one possible solution.

Cheers,
Dave

Hashes are by definition nonsortable. There is no guarantee that the
order you put them in will be the order you access them. The order
they appear in the hash probably has something to do with the hashed
value of each key (I think).

A hash's order is not guaranteed. If you want to display the hash in sorted order you can do something like the following

% cat sorted_hash.rb
class Hash
   def each_ordered_by_key
      keys.sort.each do |key|
        yield(key, self[key])
      end
   end
end

str = "{"

hash = {"plums"=>3, "bananas"=>4, "apples"=>6}

hash.each_ordered_by_key do |key, value|
   str << "#{key.inspect}=>#{value.inspect}, "
end

str[-2, 2] = "}"

puts str

% ruby sorted_hash.rb
{"apples"=>6, "bananas"=>4, "plums"=>3}

···

On Jun 14, 2006, at 3:03 AM, Oliver Katzer wrote:

Hi everyone!

is it impossible to sort a hash by key?

I have a hash like {"plums"=>3, "bananas"=>4, "apples"=>6}

And what i want is {"apples" => 6, "bananas" => 4, "plums" => 3}

Hash#sort returns an array. So i've tried this:

class Hash
  def sort_by_key
    array = self.sort
    # the array is sorted!
    array.inject({}) do |hash, value|
      hash[value.first] = value.last
      hash
    end
  end
end

But the result is {"plums"=>3, "bananas"=>4, "apples"=>6}!

So - is it impossible to sort a hash by key?

Oliver.

-- Posted via http://www.ruby-forum.com/\.

Hi everyone!

is it impossible to sort a hash by key?

I have a hash like {"plums"=>3, "bananas"=>4, "apples"=>6}

And what i want is {"apples" => 6, "bananas" => 4, "plums" => 3}

Hash#sort returns an array. So i've tried this:

class Hash
def sort_by_key
   array = self.sort
   # the array is sorted!
   array.inject({}) do |hash, value|
     hash[value.first] = value.last
     hash
   end
end
end

But the result is {"plums"=>3, "bananas"=>4, "apples"=>6}!

So - is it impossible to sort a hash by key?

Oliver.

--
Posted via http://www.ruby-forum.com/\.

Hashes are unordered, an "ordered hash" is an oxymoron.
If you need a hash to be ordered, the easiest way is to use an array.

  irb(main):001:0> hsh = {:a => 1, :b => 2, :c => 3, :d => 4}
  => {:d=>4, :b=>2, :c=>3, :a=>1}
  irb(main):002:0> hsh.sort_by { |k,v| k }
  NoMethodError: undefined method `<=>' for :d:Symbol
          from (irb):2:in `sort_by'
          from (irb):2
  irb(main):003:0> hsh.sort_by { |k,v| k.to_s }
  => [[:a, 1], [:b, 2], [:c, 3], [:d, 4]]

···

On 6/14/06, Oliver Katzer <ok@yum.de> wrote:
          from :0

--
Matt

Although an old topic, this example could be useful to someone:

h = ENV.to_hash
h.keys.sort.each{|k| puts k + " => " + h[k] + "<br>\n"}

···

--
Posted via http://www.ruby-forum.com/.

Dave, Farrel, Logan - Thanks for your quick replys!
Hash#each_ordered_by_key is a good solution for my problem.

Oliver.

···

--
Posted via http://www.ruby-forum.com/.

Hashes are unordered, an "ordered hash" is an oxymoron.
If you need a hash to be ordered, the easiest way is to use an array.

...

  => [[:a, 1], [:b, 2], [:c, 3], [:d, 4]]

And you can then use assoc to look up the corresponding element:

a = [[:a, 1], [:b, 2], [:c, 3], [:d, 4]]
a.assoc(:c)[1] #=> 3

The look-up performance for large arrays will be far inferior to that
of a hash, however.

Paul.

···

On 14/06/06, Matthew Harris <shugotenshi@gmail.com> wrote:

h={:c=> 1, :b=> 2, :a => 3}
a=
h.keys.sort_by {|s| s.to_s}.each {|key| puts h[key] }
puts a

=> [[:a, 3], [:b, 2], [:c, 1]]

-------- Original-Nachricht --------

···

Datum: Wed, 14 Jun 2006 18:48:06 +0900
Von: Paul Battley <pbattley@gmail.com>
An: ruby-talk@ruby-lang.org
Betreff: Re: impossible to sort a hash by key?

On 14/06/06, Matthew Harris <shugotenshi@gmail.com> wrote:
> Hashes are unordered, an "ordered hash" is an oxymoron.
> If you need a hash to be ordered, the easiest way is to use an array.
...
> => [[:a, 1], [:b, 2], [:c, 3], [:d, 4]]

And you can then use assoc to look up the corresponding element:

a = [[:a, 1], [:b, 2], [:c, 3], [:d, 4]]
a.assoc(:c)[1] #=> 3

The look-up performance for large arrays will be far inferior to that
of a hash, however.

Paul.

shorter:

h={:c=> 1, :b=> 2, :a => 3}
h.keys.sort_by {|s| s.to_s}.map {|key| [key, h[key]] }

-------- Original-Nachricht --------

···

Datum: Wed, 14 Jun 2006 18:48:06 +0900
Von: Paul Battley <pbattley@gmail.com>
An: ruby-talk@ruby-lang.org
Betreff: Re: impossible to sort a hash by key?

On 14/06/06, Matthew Harris <shugotenshi@gmail.com> wrote:
> Hashes are unordered, an "ordered hash" is an oxymoron.
> If you need a hash to be ordered, the easiest way is to use an array.
...
> => [[:a, 1], [:b, 2], [:c, 3], [:d, 4]]

And you can then use assoc to look up the corresponding element:

a = [[:a, 1], [:b, 2], [:c, 3], [:d, 4]]
a.assoc(:c)[1] #=> 3

The look-up performance for large arrays will be far inferior to that
of a hash, however.

Paul.

From: Peter Ertl [mailto:pertl@gmx.org]

shorter:

> h={:c=> 1, :b=> 2, :a => 3}
> h.keys.sort_by {|s| s.to_s}.map {|key| [key, h[key]] }

Shorter, faster, and (to my mind) clearer:

h.to_a.sort_by {|k,v| k.to_s }

If you're not using symbols for your keys, you can just do:

h.to_a.sort

(I'm guessing that using OrderedHash will have the same problem of
symbols not being comparable in this situation).

Daniel Sheppard wrote:

h.to_a.sort_by {|k,v| k.to_s }

Or even:

h.sort_by {|k,v| k.to_s }

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407