(我已经为下面的问题写了一个解决方案,但是想问一下是否有人可以建议一个更清洁的解决方案,更多的是在#34; Spirit" Ruby中。)
问题:我有一组(有序的)针,大海捞针中的(有序)元素集,以及带针和干草堆元素并产生真或假的谓词。任务是找到第一个针头,其中谓词为true,其中有一些haystack元素,然后返回haystack元素。我们对针头不感兴趣。针和草垛表示为阵列。
例如,如果
needles = [17,3,7,121]
haystack = [40,30,70]
,谓词是
def p(needle, hay)
hay % needle == 0
end
结果应为30,因为对于针17,haystack中没有元素满足谓词,但对于针3,第二个元素(30)可以。
这是我的实施:
found = nil
needles.find do |n|
found = haystack.find { |he| p(n,he) }
break if found
end
我觉得有点不自然的是,我基本上抛弃了外部find
的结果,需要携带变量found
,最终保存结果。我正在寻找一个更简洁的表达式,它直接将结果赋给found
,即:
found = ......
有什么想法吗?
答案 0 :(得分:1)
需要注意的重要一点是,它是您要查找的haystack
元素,而不是needle
。因此,此变量必须是最外层循环中的变量。
然后通过更加惯用来使用Enumerable#any?检查是否存在满足谓词的针,因为您实际上只关心true
/ false
返回值。 / p>
最终结果是:
haystack.find do |he|
needles.any? { |needle| p(needle, he) }
end
编辑:我稍微误解了这个问题,抱歉。如果我们订购针头,并找到第一个满足谓词“最高阶”针头的干草堆,那么我们就可以做到:
haystack
.select { |he| needles.any? { |needle| p(needle, he) } }
.min_by { |he| needles.index { |needle| p(needle, he) } }
或者作为替代(更有效)的解决方案,如何:
haystack.min_by do |he|
needles.index { |needle| p(needle, he) } || Float::INFINITY
end
如果Float::INFINITY
与needles
元素的条件匹配,则会使用haystack
这个有趣的用法,在这种情况下index
方法返回nil