通过过滤器进行Clojure分区

Ral*_*lph 13 partitioning clojure

在Scala中,分区方法将一个序列分成两个独立的序列 - 谓词为true的序列和为false的序列:

scala> List(1, 5, 2, 4, 6, 3, 7, 9, 0, 8).partition(_ % 2 == 0)
res1: (List[Int], List[Int]) = (List(2, 4, 6, 0, 8),List(1, 5, 3, 7, 9))
Run Code Online (Sandbox Code Playgroud)

请注意,Scala实现仅遍历序列一次.

在Clojure中,partition-by函数将序列拆分为多个子序列,每个子序列都是与谓词相符或不符合谓词的最长子集:

user=> (partition-by #(= 0 (rem % 2)) [1, 5, 2, 4, 6, 3, 7, 9, 0, 8])
((1 5) (2 4 6) (3 7 9) (0 8))
Run Code Online (Sandbox Code Playgroud)

split-by产品:

user=> (split-with #(= 0 (rem % 2)) [1, 5, 2, 4, 6, 3, 7, 9, 0, 8])
[() (1 5 2 4 6 3 7 9 0 8)]
Run Code Online (Sandbox Code Playgroud)

是否有内置的 Clojure函数与Scala partition方法做同样的事情?

A. *_*evy 18

我相信你正在寻找的功能是clojure.core/group-by.它返回一个键映射到原始序列中的项目列表,分组函数返回该键.如果使用true/false生成谓词,您将获得正在寻找的拆分.

user=> (group-by even? [1, 5, 2, 4, 6, 3, 7, 9, 0, 8])
{false [1 5 3 7 9], true [2 4 6 0 8]}
Run Code Online (Sandbox Code Playgroud)

如果你看一下实现,它就满足了你只需要使用一次传递的要求.此外,它使用引擎盖下的瞬态,因此它应该比迄今为止发布的其他解决方案更快.需要注意的是,您应该确定分组功能正在生成的键.如果它生成nil而不是false,那么您的地图将列出nil键下的失败项目.如果您的分组函数产生非零值而不是true,那么您可以在多个键下列出传递值.这不是一个大问题,只需要知道你需要为分组函数使用true/false生成谓词.

好处group-by是它比将序列分成传递和失败的项目更通用.您可以轻松使用此功能将序列分组为您需要的多个类别.非常有用和灵活.这也许就是为什么group-byclojure.core代替separate.