Ruby - 将数组元素值与其他元素进行比较

时间:2014-11-21 00:05:46

标签: ruby arrays

让我们说我有一系列对象(或哈希),如下所示 -

a = [ {salary: 10, products: 1}, {salary: 9, products: 1}, {salary: 10, products: 0} ]

如果数组中存在具有较高产品价值且相同薪水或更低的其他元素,我想从数组中删除元素。覆盖这两个实例的一些伪逻辑看起来像这样 -

IF EXISTS 'other element' WITH >= products and < salary THEN DELETE

IF EXISTS 'other element' WITH > products and =< salary THEN DELETE

哪些Ruby方法可以帮助我实现这个目标?

编辑:在上面的示例中,预期输出为{salary: 9, products: 1}。应该删除第一个元素,理由是另一个元素的工资较低,但产品相同(或更多)。第三个元素可以删除,理由是第一个元素有更多相同薪水的产品,或者因为第二个元素的产品更多而工资更低。

3 个答案:

答案 0 :(得分:2)

首先,替代方法

这可以通过稍微分解问题来解决。您想要使用的机制的描述使我相信您基本上试图按产品比例来计算要素:薪水。你可以通过对它们进行排序来识别这些最佳表现者(a是哈希数组):

sorted = a.sort_by{|h| Rational h[:products], h[:salary] }

从那里,您可以根据需要从数组sorted的顶部或底部略读。这可能会告诉您您正在尝试了解有关数据的内容。

但如果不是你想要的......

描述的解决方案

如果你真的希望它以你描述它的方式计算,那么你将不得不对该集合进行多次传递。我可能会使用以下函数表达式。

selected = a.map{ |h|
  h[:salary]
}.uniq.map{ |salary|
  a.select{ |h|
    h[:salary] <= salary
  }.max_by{ |h|
    h[:products]
  }
}.uniq

如果你有一个非常大的输入集,你可以优化select块以获得一些性能提升,但它不会那么容易阅读。您必须决定这对您是否重要。

请注意,这只会在每个薪资范围内选择一个元素,因此如果您有两个具有完全相同薪水和产品的元素,则最终列表中只会出现一个元素。如果你想要包含绑定的元素,那么它只会稍微复杂一些:

selected = a.map{ |h|
  h[:salary]
}.uniq.flat_map{ |salary|
  most = 0
  a.select{ |h|
    h[:salary] <= salary
  }.tap{ |group|
    most = group.map{|h| h[:products] }.max
  }.select{ |h|
    h[:products] == most
  }
}.uniq

答案 1 :(得分:1)

这样做没问题,但它不优雅或高效:

a.reject { |e1| a.any? { |e2| e1 != e2 && e2[:salary] <= e1[:salary] && e2[:products] >= e1[:products] } }

问题在于它是O(n ^ 2) - 对于数组中的每个元素,它再次遍历数组。如果效率不是一个很大的问题,那么这可能是最开始的。

我想到的唯一其他解决方案涉及将数组转换为树或其他数据结构以获得更高的效率,但这样看起来会感觉更复杂。

答案 2 :(得分:0)

一种方式:

a = [ {salary: 10, products: 1},
      {salary:  9, products: 1},
      {salary: 12, products: 0},
      {salary: 10, products: 0} ]

b = a.group_by {|h| h[:salary]}.values.map {|a| a.max_by { |h| h[:products]}}
  #=> [{:salary=>10, :products=>1},
  #    {:salary=>9, :products=>1},
  #    {:salary=>12, :products=>0}]
a.reject {|h| b.any? {|g|
  (g[:salary] <= h[:salary]) && g[:products] > h[:products]}}
  #=> [{:salary=>10, :products=>1}, {:salary=>9, :products=>1}]

b实际上是“无名的”哈希;即,唯一需要在下一步中考虑的因素。人们可以跳过这一步,但是如果未指定的哈希比例不是太大,它会提高效率。