使用带有2个参数的谓词进行过滤

Sar*_*ner 3 algorithm haskell functional-programming

我想要的基本上是对列表的O(n ^ 2)迭代.假设我有两个整数的列表,

let list = [2312, 8000, 3456, 7000, 1234]
Run Code Online (Sandbox Code Playgroud)

以及检查是否将两个整数加在一起会产生高于20000的结果的函数(这可能是一个任意函数,它接受两个整数并返回一个布尔值).

myPredicate :: Int -> Int -> Bool
myPredicate x y = x + y > 10000
Run Code Online (Sandbox Code Playgroud)

有没有办法将此谓词应用于上面的列表,以获取包含有效对的列表列表,如下所示:

>> filter myPredicate list
>> [[2312, 8000], [3456, 8000], [3456, 7000], [8000, 7000]]
Run Code Online (Sandbox Code Playgroud)

n. *_* m. 5

这直接由Haskell语法支持.

[(x, y) | x <- myList, y <- myList, x + y > 20000]
Run Code Online (Sandbox Code Playgroud)

这将返回反向和重复对.如果这不是您所需要的,请考虑以下列表理解:

[(x, y) | x <- myList, y <- myList, x < y, x + y > 20000] -- no reversed pairs, no repeats

[(x, y) | x <- myList, y <- myList, x <= y, x + y > 20000] -- repeats, no reversed pairs
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因,科学不知道你有一个重复元素的列表,比如说[30000,30000] 你只想要在不同位置的元素形成有效的对,那么这个简单的列表理解将不起作用.我不知道这会是什么样的现实生活问题,但在这里你是:

[(y,z) | (y:ys) <- tails xs, z <- ys, y + z > 20000]
Run Code Online (Sandbox Code Playgroud)

(从其他答案中窃取的想法)

  • 这将包括反转(`(2312,8000)`和`(8000,2312)`以及重复(`(8000,8000)`),这个问题似乎排除了. (3认同)

Jor*_*ano 5

如果我理解你正确你想构建对列表,

pairs xs = [(y,z) | (y:ys) <- tails xs, z <- ys]
Run Code Online (Sandbox Code Playgroud)

然后使用你的谓词过滤掉它,这个谓词需要处于未经处理的形式,

myPredicate' :: (Int,Int) -> Bool
myPredicate' x y = x + y > 10000
Run Code Online (Sandbox Code Playgroud)

所以,

filter myPredicate' (pairs list)
Run Code Online (Sandbox Code Playgroud)

或者等价的

filter (uncurry myPredicate) (pairs list)
Run Code Online (Sandbox Code Playgroud)

  • ......或`[[y,z] | (y:ys)< - tails xs,z < - ys,myPredicate'yz]`.:) (3认同)