查找数组中具有相同属性的对象集

时间:2014-03-26 18:40:11

标签: ruby arrays enumerable

鉴于我有一个包含两个属性的数组:'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 = 2class = 'center'

到目前为止,我知道如何通过dos两个属性进行分组,但之后我不知道如何获得具有更多元素的集合。

现在我有:

my_arr.group_by { |x| [x[:n_parents], x[:class]] }

4 个答案:

答案 0 :(得分:2)

这对你有用。它通过散列本身对散列进行分组,然后通过数组计数获得最大的组

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

答案 1 :(得分:0)

如下所示:

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

答案 2 :(得分:0)

我正在使用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"}]

答案 3 :(得分:0)

这是第四个要发布的答案。前面三个答案全部使用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]