Сортировка массива хэшей Ruby по количеству появлений значения - PullRequest
0 голосов
/ 04 июля 2019

У меня есть массив хэшей следующим образом:

details = [
  {:name => "Alice", :age => 20},
  {:name => "Ted",   :age => 25},
  {:name => "Poppy", :age => 33},
  {:name => "Amy",   :age => 20},
  {:name => "Ted",   :age => 90},
  {:name => "Amy",   :age => 22},
  {:name => "Ted",   :age => 23}
]

Я хочу иметь возможность сортировки, чтобы я мог заказывать, основываясь на том, сколько раз имена каждого человека появляются. Например, вывод может быть: "Ted, Ted, Ted, Amy, Amy, Alice, Poppy"

Может кто-нибудь помочь, пожалуйста? :)

Спасибо

Ответы [ 4 ]

5 голосов
/ 04 июля 2019

Получите хэш для подсчета имен, затем выполните сортировку по количеству имен:

details.each.with_object(Hash.new(0)) { |e, c| c[e[:name]] += 1 }.
    then { |c| details.sort_by { |e| -c[e[:name]] } }.
    map { |e| e[:name] }
0 голосов
/ 05 июля 2019
details.map { |h| h[:name] }.
        group_by(&:itself).
        values.
        sort_by { |a| -a.size }.
        flatten
  #=> ["Ted", "Ted", "Ted", "Amy", "Amy", "Alice", "Poppy"]

Можно добавить .join(', '), если вместо этого требуется строка:

"Ted, Ted, Ted, Amy, Amy, Alice, Poppy"

Самая дорогая операция здесь - это сортировка, которая является O (n * log (n)); все остальные операции O (n). Пусть

arr = ["Alice", "Ted", "Poppy", "Amy", "Ted", "Amy", "Ted"]

Выполняя group_by и values до sort_by, только

n = arr.uniq.size 
  #=> 4

значения должны быть отсортированы, в отличие от сортировки всех 7 элементов arr.

Шаги следующие.

b = details.map { |h| h[:name] }
  #=> ["Alice", "Ted", "Poppy", "Amy", "Ted", "Amy", "Ted"] 
c = b.group_by(&:itself)
  #=> {"Alice"=>["Alice"], "Ted"=>["Ted", "Ted", "Ted"], "Poppy"=>["Poppy"],
  #    "Amy"=>["Amy", "Amy"]} 
d = c.values
  #=> [["Alice"], ["Ted", "Ted", "Ted"], ["Poppy"], ["Amy", "Amy"]] 
e = d.sort_by { |a| -a.size }
  #=> [["Ted", "Ted", "Ted"], ["Amy", "Amy"], ["Alice"], ["Poppy"]] 
e.flatten
  #=> ["Ted", "Ted", "Ted", "Amy", "Amy", "Alice", "Poppy"] 
0 голосов
/ 04 июля 2019
output_array = []
Hash[details.group_by{|data| data[:name]}.transform_values(&:count).sort_by{|k,v| v}.reverse].each{|key,value| value.times do output_array.push(key)  end }

output_array будет иметь результаты

0 голосов
/ 04 июля 2019

будет возвращено на основе вхождения атрибута имени:

sorted_group_details = details.group_by{|d| d[:name]}.sort_by{|key, val| val.count}

по умолчанию возвращает возрастающий порядок. если вы хотите сделать заказ в большинстве случаев, просто добавьте reverse

sorted_group_details.reverse

и, если вы хотите вернуть плоский объект из сгруппированного массива:

sorted_group_details.map{|d| d[1]}.flatten
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...