使用clojure获取字符串向量中的一组唯一单词的惯用方法

Pau*_*der 0 vector clojure set

我是clojure的完全新手,所以请原谅下面的愚蠢...但我试图在空格上分割一个字符串向量,然后从单个序列中的整个结果向量中获取所有唯一字符串(我对这种序列的类型并不挑剔).这是我试过的代码.

(require '[clojure.string :as str])
(require '[clojure.set :as set])
(def documents ["this is a cat" "this is a dog" "woof and a meow"])
(apply set/union (map #(str/split % #" ") documents))
Run Code Online (Sandbox Code Playgroud)

我原以为这会返回一组独特的单词,即

#{"woof" "and" "a" "meow" "this" "is" "cat" "dog"}
Run Code Online (Sandbox Code Playgroud)

但它返回一个非唯一单词的向量,即

["woof" "and" "a" "meow" "this" "is" "a" "cat" "this" "is" "a" "dog"]
Run Code Online (Sandbox Code Playgroud)

最终,我只是在一个固定的电话中包裹它,即,

(set (apply set/union (map #(str/split % #" ") documents)))
Run Code Online (Sandbox Code Playgroud)

得到了我想要的东西:

#{"dog" "this" "is" "a" "woof" "and" "meow" "cat"}
Run Code Online (Sandbox Code Playgroud)

但我不太明白为什么会这样.根据文档,union函数返回一个集合.那我为什么要得到一个载体呢?

第二个问题:另一种方法是公正的

(distinct (apply concat (map #(str/split % #" ") documents)))
Run Code Online (Sandbox Code Playgroud)

它也返回我想要的东西,虽然是以列表形式而不是以集合形式.但是之前SO的一些讨论表明,concat异常缓慢,可能比设置操作慢(?).

这是对的......是否还有其他理由选择其他方法(或第三种方法)?

我真的不在乎是否从另一端获得了一个矢量或一组,但最终会关注性能因素.我想通过实际生产的东西,将是我的文本挖掘习惯有用的学习Clojure的,所以最终的代码,此位将是工作流程的一部分,以有效地处理大量的文本数据... ...的时间得到它现在是正确的,表现明智的,而且只是一般的非愚蠢的.

谢谢!

Sea*_*eld 7

clojure.set/union对集合进行操作但是你给它了序列(结果str/split是一串字符串).

(set (mapcat #(str/split % #" ") documents)) 应该给你你需要的东西.

mapcat将做一个懒惰的"地图和连接"操作.set将该序列转换为集合,丢弃重复序列.

  • @PaulGowder考虑具有契约的联合函数可能会有所帮助 - 程序员的合同一方是将集合传递给union,而函数的一部分就是返回一个集合.传递向量而不是集合打破了合同,因此工会可能会或可能不会完成交易的结束.如果它报告了有关其输入的错误,它可能不那么令人不安,但随着时间的推移,您可能会认为这不是一个问题. (2认同)