我有一个类似
的字符串集合["snowy10" "catty20" "manny20" "snowy20" "catty10" "snowy20" "catty30" "manny10" "snowy20" "manny30"]
希望将其转换为基于字符串的前五个字符分组的集合的集合。
[["snowy10" "snowy20" "snowy20"] ["catty10" "catty20""catty30"]["manny10" ""manny20"" "manny20"]]
在Clojure中寻找解决方案。
答案 0 :(得分:5)
group-by
功能在这里很有帮助:
clojure.core/group-by ([f coll]) Returns a map of the elements of coll keyed by the result of f on each element. The value at each key will be a vector of the corresponding elements, in the order they appeared in coll.
换句话说,group-by
使用给定的函数f
为coll
中的每个元素生成一个键,并且与该键关联的值是该元素的累积元素的向量键。
在您的示例中,如果我们知道保证所有输入字符串都至少包含5个字符,则可以使用subs
。但是使用take
构建更通用的健壮解决方案更加容易:
(def strings ["snowy10" "catty20" "manny20" "snowy20" "catty10" "snowy20" "catty30" "manny10" "snowy20" "manny30"])
(group-by (partial take 5) strings)
给予我们
{(\s \n \o \w \y) ["snowy10" "snowy20" "snowy20" "snowy20"]
(\c \a \t \t \y) ["catty20" "catty10" "catty30"]
(\m \a \n \n \y) ["manny20" "manny10" "manny30"]}
这不是我们想要的-我们只需要地图值。为此,我们使用vals
:
(-> (group-by (partial take 5) strings)
(vals))
我们得到:
(["snowy10" "snowy20" "snowy20" "snowy20"]
["catty20" "catty10" "catty30"]
["manny20" "manny10" "manny30"])
更改分组条件就像更改我们提供给group-by
的“键”功能一样简单。例如,我们可以使用take-last
按每个字符串的最后两个字符分组:
(-> (group-by (partial take-last 2) strings)
(vals))
给出:
(["snowy10" "catty10" "manny10"]
["catty20" "manny20" "snowy20" "snowy20" "snowy20"]
["catty30" "manny30"])
答案 1 :(得分:3)
user> (def v ["snowy10" "catty20" "manny20" "snowy20" "catty10" "snowy20" "catty30" "manny10" "snowy20" "manny30"])
#'user/v
user> (vals (group-by #(subs % 0 5) v))
(["snowy10" "snowy20" "snowy20" "snowy20"]
["catty20" "catty10" "catty30"]
["manny20" "manny10" "manny30"])
答案 2 :(得分:1)
如何用\d
分割字符串,像这样:
user=> (def v ["snowy10" "catty20" "manny20" "snowy20" "catty10" "snowy20" "catty30" "manny10" "snowy20" "manny30"])
#'user/v
user=> (vals (group-by #(first (clojure.string/split % #"\d")) v))
(["snowy10" "snowy20" "snowy20" "snowy20"]
["catty20" "catty10" "catty30"]
["manny20" "manny10" "manny30"])