假设有如下序列:
["ab" "ba" "ac" "ca" "bc" "cc"]
Run Code Online (Sandbox Code Playgroud)
我想知道频率,但键应排序字符串.简而言之,我希望得到如下结果:
{"ab" 2, "ac" 2, "bc" 1, "cc" 1}
Run Code Online (Sandbox Code Playgroud)
Clojure有frequencies功能,但它不接受关键功能.所以,通常我可以通过组合group-by和来做到这一点map:
(->> ["ab" "ba" "ac" "ca" "bc" "cc"]
(group-by #(apply str (sort %)))
(map (fn [[k vs]] [k (count vs)]))
(int {}))
Run Code Online (Sandbox Code Playgroud)
但是,这看起来很冗长.即使在Java中,我也可以使用Stream API同时进行分组和计数,如下所示:(假设有一个方法sortedStr(s)
Arrays.asList("aa", "ab", "ab", "bb", "cc" , "ca")
.stream()
.collect(groupingBy(s->sortedStr(s), counting()));
Run Code Online (Sandbox Code Playgroud)
是否有任何方法可以像Java8一样在clojure中进行分组和计数?
这是一个使用内置frequencies函数的Clojure版本.
(frequencies (map #(apply str (sort %))
["ab" "ba" "ac" "ca" "bc" "cc"]))
;;=> {"ab" 2, "ac" 2, "bc" 1, "cc" 1}
Run Code Online (Sandbox Code Playgroud)
我可能错了,但Java版本已经在您的示例中获取了排序键.在这种情况下,它只是frequencies在Clojure中调用(如果我理解你的问题).
编辑:看起来Java版本在此期间得到纠正,所以我的上一条评论已经过时了.
@Stefan 的答案效果很好,但它并不是最有效的,因为它首先映射 coll(产生一个中间集合),然后找到频率。因此,它并不真正符合您问题的“分组并立即计数”部分。我宁愿去reduce:
user> (reduce #(update %1 (apply str (sort %2)) (fnil inc 0))
{} ["ab" "ba" "ac" "ca" "bc" "cc"])
{"ab" 2, "ac" 2, "bc" 1, "cc" 1}
Run Code Online (Sandbox Code Playgroud)