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

clojure improve readability of filter a two-dimensional list

当前代码采用如下输入: [[: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 操作,我们可以一次收集具有相同键的所有项目。

(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 () %))))