1

My hash looks like below. I want the output to be in the same hash form but with hash arranged according to the price.

{
  1=>{
    "name"=>"Mark", 
    "date"=>"27/08/2015", 
    "bed"=>"3", 
    "furnish"=>"Fully", 
    "size"=>"10", 
    "price"=>790000
  }, 
  2=>{
    "name"=>"Mark", 
    "date"=>"27/08/2015", 
    "bed"=>"3", 
    "furnish"=>"Fully", 
    "size"=>"10", 
    "price"=>720000
  }, 
  3=>{
    "name"=>"Mark", 
    "date"=>"27/08/2015", 
    "bed"=>"3", 
    "furnish"=>"Fully", 
    "size"=>"10", 
    "price"=>750000
  }, 
  4=>{
    "name"=>"Mark", 
    "date"=>"27/08/2015", 
    "bed"=>"3", 
    "furnish"=>"Fully", 
    "size"=>"10", 
    "price"=>710000
  }
} 

I've read from How to sort a Ruby Hash by number value? but it is just with one nested hash. Totally clueless with how I could achieve that. Would be grateful if any of you are willing to help me.

Community
  • 1
  • 1
ikanyu
  • 305
  • 4
  • 14
  • Your "hash" is invalid (not complete). – sawa Aug 31 '15 at 06:00
  • Since you do not describe otherwise, by default, your question implies that you want to sort by the price as strings. Is this correct? – sawa Aug 31 '15 at 06:02
  • 1
    @sawa : I just edited the hash. Sorry for the error. I only took parts of the has only. For the string part, I actually managed to change it into integer. Anyway, I have edited the code – ikanyu Aug 31 '15 at 06:05
  • Next time, please shrink your example down to the minimum. Here, for example, this would have just as good: `h = { 1=>{ "name"=>"Bubba", "price"=>79 }, 2=>{ "name"=>"Wilma", "price"=> 72 }, 3=>{ "name"=>"Billy-Bob", "price"=>62 } }`. Also, assign each input to a variable (here I set the hash equal to `h`), so that those giving answers can refer to those variables without having to define them. – Cary Swoveland Aug 31 '15 at 07:16
  • @Cary, thanks for your comment! I will keep that in mind :) – ikanyu Aug 31 '15 at 07:39
  • Two other things: 1) When you give examples, it's generally best to show your desired result, though that may not be necessary here, as it can be described easily. On the other hand, had you used a simplified input, the desired output would require little space. 2) When you edit your question, you should make it clear that it's an edit (e.g., **Edit:...**) if it changes the question substantively, else you may render answers or comments puzzling (e.g., the selected answer here) or meaningless. It's not enough to explain in a comment. – Cary Swoveland Aug 31 '15 at 19:40
  • @CarySwoveland: That's a really detailed explanation on how I could improve my questions better :) I am really really grateful about that!! thanks a lot!! – ikanyu Sep 01 '15 at 05:52

2 Answers2

5

Try this:

> myhash.sort_by{|_,v| v["price"]}.to_h
#=> 
    {
      4=>
        {
          "name"=>"Mark", 
          "date"=>"27/08/2015", 
          "bed"=>"3", 
          "furnish"=>"Fully", 
          "size"=>"10", 
          "price"=>710000
        }, 
      2=>
        {
          "name"=>"Mark", 
          "date"=>"27/08/2015", 
          "bed"=>"3", 
          "furnish"=>"Fully", 
          "size"=>"10", 
          "price"=>720000
        }, 
      3=>
        {
          "name"=>"Mark", 
          "date"=>"27/08/2015", 
          "bed"=>"3", 
          "furnish"=>"Fully", 
          "size"=>"10", 
          "price"=>750000
        }, 
      1=>
        {
          "name"=>"Mark", 
          "date"=>"27/08/2015", 
          "bed"=>"3", 
          "furnish"=>"Fully", 
          "size"=>"10", 
          "price"=>790000
        }
    } 

Update:

If you have price in string like "15,000" then you can remove comma seprator and convert it to integer like:

> "15,000"
> "15,000".tr(',', '').to_i
#=> 15000

So code would be like:

> myhash.sort_by{|_,v| v["price"].tr(',', '').to_i}.to_h
Gagan Gami
  • 10,121
  • 1
  • 29
  • 55
  • Hi @Gagan, I am keen to learn how you would do if the price is written in string "790,000" or even "1,250,000"? Still pretty new in programming would love to see how other ppl did :) – ikanyu Aug 31 '15 at 06:19
  • @ikanyu : if price is in string then you can convert it to integer. If price is in string then in my code you can replace `v["price"]` with `v["price"].tr(',', '').to_i`. Hope this will help you – Gagan Gami Aug 31 '15 at 06:45
1

If your data (hash) is assigned to the variable h then you can sort it by price using this code:

h.sort_by {|key, value| value['price'].to_f}

It gives you an array of [key,value] pairs. To convert it back to hash, you can use:

Hash[h.sort_by {|key, value| value['price'].to_f}]

In recent versions of Ruby (2.1+) you can use to_h method as well.

Update:

Because you changed price to numeric value, to_f conversion is not required any more. So the final code looks like this:

h.sort_by {|key, value| value['price']}.to_h

dimakura
  • 7,575
  • 17
  • 36
  • Hi @dimakura, I am keen to learn how you would do if the price in the hash is written in string "790,000" or even "1,250,000"? Still pretty new in programming would love to see how other ppl did :) – ikanyu Aug 31 '15 at 06:24
  • @ikanyu, if the price is string then you use `to_f` method to convert it to `Float` numeric type. The code then look: `h.sort_by {|key, value| value['price'].to_f}.to_h` – dimakura Aug 31 '15 at 06:26
  • sorry for bothering you again. I realise the number to.f works fine until 999,999. However, when there is price like "1,250,000", to.f changes it to 1.0 . then, in the whole hash, "1,250,000" will become the smallest number. Is there any way to fix this? – ikanyu Aug 31 '15 at 06:42
  • Do you mean price is written just like "1,250,000" or "1250000"? If it's "1,250,000", then you should remove commas: `"1,250,000".gsub(',','').to_i` – dimakura Aug 31 '15 at 06:46
  • The code is then `h.sort_by {|key, value| value['price'].gsub(',','').to_f}.to_h` – dimakura Aug 31 '15 at 06:46