简体   繁体   中英

How to sort array of hashes by value?

I'm trying to sort an array of hashes based on the given key-value, and will return that value on top of the array first, then preceded by the remaining data.

Example would be:

students = [{name: "John Doe", age: 16, adviser: "Mrs. Robinson"},
            {name: "John Smith", age: 18, adviser: "Mrs. Williams"},
            {name: "Michael Rodriguez", age: 17, adviser: "Mr. Lee"}]

def sort_by_adviser(data, name)
  ...
end

> sort_by_adviser(students, "Mr. Lee")
=> [{name: "Michael Rodriguez", age: 17, adviser: "Mr. Lee"},
    {name: "John Doe", age: 16, adviser: "Mrs. Robinson"},
    {name: "John Smith", age: 18, adviser: "Mrs. Williams"}]

> sort_by_adviser(students, "Mrs. Williams")
=> [{name: "John Smith", age: 18, adviser: "Mrs. Williams"},
    {name: "Michael Rodriguez", age: 17, adviser: "Mr. Lee"},
    {name: "John Doe", age: 16, adviser: "Mrs. Robinson"}]

Here the output brings the adviser's name on top of the list, then preceded by other hashes in the array.

> sort_by_keyvalue(data, "Z")
=> [{letter: 'Z'},
    {letter: 'A'},
         .
         .
         .
    {letter: 'Y'}]

> sort_by_keyvalue(data, 5)
=> [{number: 5, value: 'value1'},
    {number: 5, value: 'value2'},
    {number: 5, value: 'value3'},
    {number: 9, value: 'value1'},
    {number: 9, value: 'value2'},
    {number: 8, value: 'value1'},
    {number: 8, value: 'value2'},
    {number: 7, value: 'value1'},
    {number: 6, value: 'value1'},
    {number: 4, value: 'value1'},
    {number: 3, value: 'value1'},
    {number: 2, value: 'value1'},
    {number: 1, value: 'value1'},
    {number: 1, value: 'value2'},
    {number: 0, value: 'value1'}]

Anyone knows how to do it?

Another implemention :)

def sort_by_adviser(data, name)
    data.each_with_index do |hash,index|
      if hash[:adviser]==name
         data.delete_at index #delete from array
         data.unshift hash
         break
      end
    end
   data
end

 > sort_by_adviser(students, "Mr. Lee")  
 #=> [{:name=>"Michael Rodriguez", :age=>17, :adviser=>"Mr. Lee"}, {:name=>"John Doe", :age=>16, :adviser=>"Mrs. Robinson"}, {:name=>"John Smith", :age=>18, :adviser=>"Mrs. Williams"}] 
def creamy_sort(key, value, arr)
  top, bottom = arr.partition{|e| e[key] == value }
  top.concat(bottom.sort{|a,b| b[key] <=> a[key]})
end

creamy_sort(:adviser, "Mr. Lee", students)

You can do that:

def sort_by_adviser(data, name)
  data = data.sort{|x,y|x[:adviser] <=> y[:adviser]}
  i = data.index{|h|h[:adviser] = name}
  h = data.delete_at i
  data.unshift h
end

I have this solution:

students = [{name: "John Doe", age: 16, adviser: "Mrs. Robinson"},
            {name: "John Smith", age: 18, adviser: "Mrs. Williams"},
            {name: "Michael Rodriguez", age: 17, adviser: "Mr. Lee"}]

def sort_by_adviser(data, *name)
  data.sort_by{| entry |    
    [ 
      name.index(entry[:adviser]) || 999,
      entry[:age], entry[:name] #2nd sort criteria
    ]
  }
end

p sort_by_adviser(students, "Mr. Lee")
#[{:name=>"Michael Rodriguez", :age=>17, :adviser=>"Mr. Lee"}, {:name=>"John Doe", :age=>16, :adviser=>"Mrs. Robinson"}, {:name=>"John Smith", :age=>18, :adviser=>"Mrs. Williams"}]

p sort_by_adviser(students, "Mrs. Williams")
# [{:name=>"John Smith", :age=>18, :adviser=>"Mrs. Williams"}, {:name=>"John Doe", :age=>16, :adviser=>"Mrs. Robinson"}, {:name=>"Michael Rodriguez", :age=>17, :adviser=>"Mr. Lee"}]

I didn't understand, what's the sorting of the remaining entry.

You wrote: then preceded by the remaining data. What's tho order criteria of the hash?

I selected age, followed by name. But you may adapt it for your need.

def weird_sort(array, key, value)
  return array.sort_by{|d| 2 <=> (d[key] == value).object_id}
end

This is based on the fact that true.object_id equals 2 in ruby. Kind of a weird solution that's why it's a weird_sort :p It also messes around the other value ordering ... so it only guarantees you that values that are equal go on top!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM