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

Vector 使用clojure获取字符串向量中唯一单词集的惯用方法,vector,clojure,set,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 (m

我是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))
我本以为这会返回一组独特的单词,即

#{"woof" "and" "a" "meow" "this" "is" "cat" "dog"}
["woof" "and" "a" "meow" "this" "is" "a" "cat" "this" "is" "a" "dog"]
但它返回一个非唯一单词的向量,即

#{"woof" "and" "a" "meow" "this" "is" "cat" "dog"}
["woof" "and" "a" "meow" "this" "is" "a" "cat" "this" "is" "a" "dog"]
最终,我只是将其包装在一个集合调用中,即

(set (apply set/union (map #(str/split % #" ") documents)))
得到了我想要的:

#{"dog" "this" "is" "a" "woof" "and" "meow" "cat"}
但我不太明白为什么会这样。根据该函数,union函数返回一个集合。为什么我会得到一个向量

第二个问题:另一种方法只是

(distinct (apply concat (map #(str/split % #" ") documents)))
它还返回我想要的,尽管是列表形式而不是集合形式。但一些讨论表明,concat异常缓慢,可能比set操作慢

是这样吗。。。还有没有其他理由选择一种方法而不是另一种方法或第三种方法

我真的不在乎从另一端得到一个向量还是一个集合,但最终会关心性能方面的考虑。我试图通过实际生成一些对我的文本挖掘习惯有用的东西来学习Clojure,因此最终这段代码将成为高效处理大量文本数据的工作流的一部分。。。现在是时候做出正确的决定了,表现明智,只是一般性的不愚蠢明智

谢谢

clojure.set/union对集合进行操作,但您为它指定了序列,而str/split的结果是字符串序列

set mapcat str/split%文档应提供您所需的内容

mapcat将执行延迟映射和连接操作。set会将该序列转换为set,并在转换过程中丢弃重复的序列。

clojure.set/union对set进行操作,但您给了它序列,而str/split的结果是字符串序列

set mapcat str/split%文档应提供您所需的内容


mapcat将执行延迟映射和连接操作。set将把序列转换成set,并在转换过程中丢弃重复的序列。

谢谢。我假设不管传递什么,union函数都会返回一个集合。。。我想不会吧@PaulGowder想象一下union函数有一个约定可能会有所帮助——约定的程序员端是将集合传递给union,约定的函数端是返回一个集合。传递向量而不是集合打破了合同,所以工会可能会也可能不会履行其交易的目的。如果它报告了输入错误,可能不会那么令人不安,但随着时间的推移,您可能会认为这不是一个问题。@PaulGowder如果查看源代码,您会发现clojure.set/union将较小集合的元素合并到较大集合中。因此,例如,clojure.set/union set range 10 range 3起作用,但是clojure.set/union set range 3n range 10返回序列21 0 1 2 3 4 6 7 8 9。正如@Brian所暗示的,您必须将此行为视为实现的意外事件,将来可能会发生变化。谢谢。我假设不管传递什么,union函数都会返回一个集合。。。我想不会吧@PaulGowder想象一下union函数有一个约定可能会有所帮助——约定的程序员端是将集合传递给union,约定的函数端是返回一个集合。传递向量而不是集合打破了合同,所以工会可能会也可能不会履行其交易的目的。如果它报告了输入错误,可能不会那么令人不安,但随着时间的推移,您可能会认为这不是一个问题。@PaulGowder如果查看源代码,您会发现clojure.set/union将较小集合的元素合并到较大集合中。因此,例如,clojure.set/union set range 10 range 3起作用,但是clojure.set/union set range 3n range 10返回序列21 0 1 2 3 4 6 7 8 9。正如@Brian所暗示的,您必须将此行为视为实现的意外事件,将来可能会发生变化。