简体   繁体   English

Haskell:根据列表中所有其他元素的谓词过滤列表

[英]Haskell: Filtering a list based on a predicate for all other elements in the list

I have a list of natural numbers [1..n] (this list is never empty) and I would like to filter each element by testing a predicate with all other elements in the list.我有一个自然数列表[1..n] (这个列表永远不会为空),我想通过测试一个包含列表中所有其他元素的谓词来过滤每个元素。 I would like to return a list of those numbers who never fulfilled the predicate.我想返回那些从未满足谓词的数字的列表。 My idea is this:我的想法是这样的:

filter (\x -> 1 == length [y| y <- [1..n], pred y x]) [1..n]

I am testing if the length is equal to 1 since for x==y the predicate returns true.我正在测试长度是否等于 1,因为对于x==y谓词返回 true。

This does work as intended, however, I was wondering if there is a cleaner way to do this.这确实按预期工作,但是,我想知道是否有更清洁的方法来做到这一点。 I'm not really looking for more performance, but rather a more simple solution.我并不是真的在寻找更高的性能,而是一个更简单的解决方案。

As far as complexity, I don't think you can do better than quadratic, since, after all, the very definition of the problem is to test each element with each other.就复杂性而言,我认为你不能比二次方做得更好,因为毕竟问题的定义是相互测试每个元素。 So unless there is more to be known about the structure of the problem, you're stuck there.因此,除非对问题的结构有更多了解,否则您将陷入困境。

But you can perhaps cut down on the performance somewhat by stopping early.但是您也许可以通过提前停止来稍微降低性能。 Calculating length every time means enumerating all elements from 1 to n , but you don't actually need that, right?每次计算length意味着枚举从1n所有元素,但您实际上并不需要它,对吗? You can stop enumerating once pred returns True for the first time.您可以在pred第一次返回True停止枚举。 To do that you can use and :为此,您可以使用and

filter (\x -> and [not (pred y x) | y <- [1..n], y /= x]) [1..n]

Or, alternatively, you can move the predicate to the condition part and then test the resulting list for emptiness:或者,您可以将谓词移动到条件部分,然后测试结果列表是否为空:

filter (\x -> null [y <- [1..n], y /= x && pred y x]) [1..n]

But I like the former variant better, because it better describes the intent.但我更喜欢前一个变体,因为它更好地描述了意图。

Finally, I think this would look cleaner as a list comprehension:最后,我认为作为列表理解,这看起来更清晰:

[ x
| x <- [1..n]
, and [not (pred y x) | y <- [1..n], y /= x]
]

But that's a matter of personal taste, of course.但这当然是个人品味的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM