質問

Given that I have an array with two attributes: 'n_parents' and 'class', which looks like this:

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'}]

I would like to get an array with the objects that share most of those two attributes. So in the previous example:

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

Because there are three objects that share n_parents = 2, and class = 'center'.

So far, I know how can I group by dos two attributes, but after that I am not sure how to get the set that has more elements.

Right now I have:

my_arr.group_by { |x| [x[:n_parents], x[:class]] }
役に立ちましたか?

解決

This should work for you. It groups the hashes by the hash itself and then gets the largest group by the array count

 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"}]

他のヒント

something like below :

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"}]

I am using code used by OP and extending over that to get result he wants:--

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

Output

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

This is the fourth answer to be posted. The three earlier answers all employed group_by/max_by/last. Sure, that may be the best approach, but is it the most interesting, the most fun? Here are a couple other ways to generate the desired result. When

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'}]

the desired result is:

  #=> [{: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]
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top