我认为有几种方法可以做到这一点。
重用过滤器
例如,我们可以使用归纳方法,基于您的元组将由两个元素组成的事实,第一个是满足谓词的元素列表,第二个是不满足谓词的元素列表。因此,您可以将过滤器功能重用为:
fun partition f xs = (filter f xs, filter (not o f) xs)
不过,这不是最好的方法,因为它对列表进行了两次评估,但如果列表很小,这是非常明显且非常易读的。
折叠式的
考虑这一点的另一种方法是折叠。您可能认为您正在将您的列表缩减为一个元组列表,并且随着您的进行,您根据谓词拆分您的项目。有点像这样:
fun parition f xs =
let
fun split x (xs,ys) =
if f x
then (x::xs,ys)
else (xs, x::ys)
val (trueList, falseList) = List.foldl (fn (x,y) => split x y)
([],[]) xs
in
(List.rev trueList, List.rev falseList)
end
分区
您也可以像 SML 的 List.parition 方法一样实现自己的折叠算法:
fun partition f xs =
let
fun iter(xs, (trueList,falseList)) =
case xs of
[] => (List.rev trueList, List.rev falseList)
| (x::xs') => if f x
then iter(xs', (x::trueList,falseList))
else iter(xs', (trueList,x::falseList))
in
iter(xs,([],[]))
end
使用 SML 基法
最终,您可以避免所有这些并使用 SML 方法List.partition,其文档说:
隔断层
将 f 应用于 l 的每个元素 x,从左到右,并返回一个对 (pos, neg),其中 pos 是那些 x 的列表,其中 fx 评估为真,而 neg 是那些 x 的列表,fx 评估为错误的。pos 和 neg 的元素保留了它们在 l 中所拥有的相同的相对顺序。
此方法与前面的示例一样实现。