clojure提高了过滤二维列表的可读性



当前代码接受如下输入:[[:k1 0] [:k1 1] [:k2 2]]并将具有相同关键字的项目组织在列表中:(([:k1 0] [:k1 1]) ([:k2 2]))

下面的代码是有效的,但我觉得这是可以改进的。嵌套的map #(filter看起来很难看,我想我可以使用clojure for函数用优雅的代码产生同样的结果。

如何提高可读性

(defn list-of-equals [itens]
  (let [get-key (fn [[k]] k)
        keys (->> itens (map get-key) distinct)
        pairs (map #(filter (fn [[k]]
                              (= % k)) itens)  keys)]
      pairs))

您面临的问题是,您必须对每个不同键的列表进行迭代。如果您使用for,它可能看起来像这样。

(defn for-filter [items val]
  (for [i items
        :when (= (first i) (first val))]
    i))

虽然这可能有点干净,但使用标准库可以使其更加简洁。如果我们通过操作进行分组,我们可以在一次通行证中收集具有相同密钥的所有项目

(group-by first items)
    => {:k1 [[:k1 0] [:k1 1]], :k2 [[:k2 2]]}

您可以使用vals 丢弃密钥

(vals (group-by first items))
    => ([[:k1 0] [:k1 1]] [[:k2 2]])

这与您的解决方案有点不同

 (([:k1 0] [:k1 1]) ([:k2 2])) 

 ([[:k1 0] [:k1 1]] [[:k2 2]]))

如果这很重要:

(map #(into () %) result)

最终的解决方案看起来像:

(defn list-of-equals [items]
    (->> (vals (group-by first items))
         (map #(into () %))))

最新更新