【问题标题】:clojure improve readability of filter a two-dimensional listclojure 提高过滤二维列表的可读性
【发布时间】:2015-12-31 20:30:16
【问题描述】:

当前代码接受如下输入: [[: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))

【问题讨论】:

  • (vals (group-by first itens))
  • 嗯,这看起来可读._。谢谢
  • 抱歉,如果我能抽出时间写出完整解释为什么会替换代码,我会
  • 您的算法由于其复杂性而需要改进。在这种情况下,可读性是第二个问题。请注意,它需要遍历在O(n²) 中执行的每个不同键的整个序列。 @noisesmith 解决方案解决了这两个问题。

标签: clojure code-readability


【解决方案1】:

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

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

虽然这可能更简洁一些,但使用标准库可以使其更简洁。如果我们进行 group-by 操作,我们可以一次收集所有具有相同 key 的项目。

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

【讨论】:

  • fyi - clojure 的 = 认为向量和列表如果具有相同的内容,则它们是相等的
  • 谢谢,我已经更新了答案,使其更加准确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 2010-11-10
  • 2014-03-31
  • 2010-09-08
  • 1970-01-01
相关资源
最近更新 更多