Найти набор объектов в массиве с одинаковыми атрибутами

Учитывая, что у меня есть массив с двумя атрибутами: 'n_parents' и 'class', который выглядит так:

my_arr = [{n_parents: 10, class: 'right'}, {n_parents: 10, class: 'right'}, {n_parents: 5, class: 'left'}, {n_parents: 2, class: 'center'}, {n_parents: 2, class: 'center'}, {n_parents: 2, class: 'center'}]

Я хотел бы получить массив с объектами, которые разделяют большинство этих двух атрибутов. Итак, в предыдущем примере:

result = [{n_parents: 2, class: 'center'}, {n_parents: 2, class: 'center'}, {n_parents: 2, class: 'center'}]

Потому что есть три объекта, которые разделяют n_parents = 2, а class= 'center'.

До сих пор я знаю, как я могу группировать по двум атрибутам dos, но после этого я не уверен, как получить набор, содержащий больше элементов.

Прямо сейчас у меня есть:

my_arr.group_by { |x| [x[:n_parents], x[:class]] }
4 ответа

Это должно сработать для вас. Он группирует хэши сам хэш и затем получает наибольшую группу по количеству массивов

my_arr = [{n_parents: 10, class: 'right'}, {n_parents: 10, class: 'right'}, {n_parents: 5, class: 'left'}, {n_parents: 2, class: 'center'}, {n_parents: 2, class: 'center'}, {n_parents: 2, class: 'center'}]
 my_arr.group_by { |h| h }.max_by { |h,v| v.count }.last
 #=>[{:n_parents=>2, :class=>"center"}, {:n_parents=>2, :class=>"center"}, {:n_parents=>2, :class=>"center"}]


Это четвертый ответ, который будет опубликован. Три предыдущих ответа на все занятые group_by/max_by/last. Конечно, это лучший подход, но самое интересное, самое интересное? Вот несколько других способов генерации желаемого результата. когда

my_arr = [{n_parents: 10, class: 'right' }, {n_parents: 10, class: 'right' },
 {n_parents: 5, class: 'left' }, {n_parents: 2, class: 'center'},
 {n_parents: 2, class: 'center'}, {n_parents: 2, class: 'center'}]

желаемый результат:

#=> [{:n_parents=>2, :class=>"center"},
 # {:n_parents=>2, :class=>"center"},
 # {:n_parents=>2, :class=>"center"}]

# 1

# Create a hash 'g' whose keys are the elements of 'my_arr' (hashes)
# and whose values are counts for the elements of 'my_arr'.
# 'max_by' the values (counts) and construct the array. 

el, nbr = my_arr.each_with_object({}) { |h,g| g[h] = (g[h] ||= 0) + 1 }
 .max_by { |_,v| v } 
arr = [el]*nbr

# 2

# Sequentially delete the elements equal to the first element of 'arr',
# each time calculating the number of elements deleted, by determining
# 'arr.size' before and after the deletion. Compare that number with the
# largest number deleted so far to find the element with the maximum
# number of instances in 'arr', then construct the array. 

arr = my_arr.map(&:dup)
most_plentiful = { nbr_copies: 0, element: [] }
until arr.empty? do
 sz = arr.size
 element = arr.delete(arr.first)
 if sz - arr.size > most_plentiful[:nbr_copies]
 most_plentiful = { nbr_copies: sz - arr.size, element: element }
 end
end
arr = [most_plentiful[:element]]* most_plentiful[:nbr_copies]


Я использую код, используемый OP и распространяющийся на него, чтобы получить результат, который он хочет:

my_arr.group_by { |x| [x[:n_parents], x[:class]] }.max_by{|k,v| v.size}.last

Вывод

#=> [{:n_parents=>2, :class=>"center"}, {:n_parents=>2, :class=>"center"}, {:n_parents=>2, :class=>"center"}]


что-то вроде ниже:

my_arr.group_by(&:values).max_by { |_,v| v.size }.last
# => [{:n_parents=>2, :class=>"center"},
# {:n_parents=>2, :class=>"center"},
# {:n_parents=>2, :class=>"center"}]

licensed under cc by-sa 3.0 with attribution.