Ruby-将数组元素值与其他元素进行比较
假设我有一个对象数组(或散列),如下所示-Ruby-将数组元素值与其他元素进行比较,ruby,arrays,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
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}
。第一个要素应该删除,因为还有另一个要素工资较低,但产品相同(或更高)。可以删除第三个元素,理由是第一个元素在相同的薪水下有更多的产品,或者因为第二个元素的薪水越低,产品就越多。这可以正常工作,但并不优雅或高效:
a.reject { |e1| a.any? { |e2| e1 != e2 && e2[:salary] <= e1[:salary] && e2[:products] >= e1[:products] } }
a.reject{e1 | a.any?{e2 | e1!=e2&&e2[:工资]=e1[:产品]}
问题是它是O(n^2)-对于数组中的每个元素,它都会再次遍历数组。如果效率对你来说不是一个大问题,那么这可能是最清楚的开始
想到的唯一其他解决方案包括将阵列转换为树或其他数据结构以获得更好的效率,但这看起来和感觉上都要复杂得多。一种方法:
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}]
a=[{salary:10,products:1},
{工资:9,产品:1},
{工资:12,产品:0},
{工资:10,产品:0}]
b=a.group|u by{h | h[:salary]}.values.map{a | a.max_by{h | h[:products]}
#=>[{:salary=>10,:products=>1},
#{:salary=>9,:products=>1},
#{:工资=>12,:产品=>0}]
a、 拒绝{h{124; b.any{124; g|
(g[:工资]h[:产品]}
#=>[{:salary=>10,:products=>1},{:salary=>9,:products=>1}]
b
实际上是“未终止的”散列;即,下一步中需要考虑的唯一散列。可以跳过这一步,但如果未终止的散列的比例不太大,则会提高效率。首先,另一种方法
这可以通过对问题进行一点分解来解决。对您想要采用的机制的描述使我相信,您基本上是在尝试按产品与工资的比率对元素进行排序。您可以通过这样对它们进行排序(a是哈希数组)一次识别出这些表现最好的元素:
sorted=a.sort_按{| h | Rational h[:products],h[:salary]}
从那里,你可以随意地从数组的顶部或底部浏览排序的。这可能会告诉你你想要了解的数据
但如果这不是你真正想要的
如上所述的解决方案
如果您真的希望它按照您描述的方式计算,那么您必须对集合进行多次传递
selected=a.map{h|
h[:工资]
}.uniq.map{|薪水|
a、 选择{| h|
h[:工资]Array#max_by and Array#delete_if或Array#rejects我知道这些方法,但是如何将它们与其他元素进行比较呢?我在想办法使用select
或include
来引用块内的数组,看看是否存在这种情况。如果知道这些方法,只需使用delete_if或reject,那么我们为什么还要谈论这个呢?这是一个单行程序。你不需要将它们与其他元素进行比较,只需找到要测试的值,然后使用它来构建数组的谓词#拒绝。@IronSavior不是每个元素测试的值都不同吗?这就是我理解问题的方式。你的代码返回[{:salary=>9,:products=>1}]
,我认为这是不正确的。@CarySwoveland这是正确的。再看看给定的数据。所有其他的工资都更高。如果有另一个元素具有更高的产品值,那么一个元素将被拒绝,并且…我们可以就此停止。没有h
的元素[products'=>1
将被拒绝,因为不存在产品值大于1
@Caryswovel的元素,并且输出应为[{:salary=>9,:products=>1}]
。是的,我看到了编辑。问题是矛盾的。真是一团糟!这实际上与我所寻找的最接近。出于某种原因,它并没有提供我所知道的正确的所需输出。我的实际程序使用了一个对象数组,但为了解释,我在示例中对其进行了简化。这就是我要介绍的ying nowa=a.delete_如果{e1 | a.any?{e2 | e1!=e2&&e2.sum(&:salary)=e1.sum(&:score)}
,此逻辑在数组上运行多次,因为数组中添加了更多的元素。但是,删除时似乎没有充分考虑到分数。
。单行程序的问题是它们很难调试!看起来该代码与我发布的代码完全相同,因此应该可以工作。如果发布一些使用对象的测试数据我可以看一看,否则从这里很难做更多的事情。Dave,我发现了问题。我的内部数组可以彼此重复,所以它们彼此匹配,因为逻辑包括“或等于”。我只是将评分标准设置为大于,以避免出现这种情况,并在运行这一行程序之前删除重复项。我还将&
切换到和,这似乎有助于解决其他一些问题。最终结果-a.reject!{e1 | a.any?{e2 | e1!=e2和e2.sum(&:salary)e1.sum(&:score)}
谢谢你的帮助!太好了!我唯一担心的是和实际上并不等同于&&
,所以这不应该是真的