Clojure:为什么要扁平化"使用错误的东西"

时间:2014-08-07 12:45:13

标签: clojure flatten

自从我开始使用Clojure以来,我已经多次阅读过这类文章。

例如,在这里:How to convert map to a sequence?

在一些推文中,我并不记得确实或多或少地说过#34;如果你正在使用扁平化你可能会做错了#34;。

我想知道,flatten有什么问题?

3 个答案:

答案 0 :(得分:5)

我认为这就是他们在你联系的答案中所谈论的内容:

so> ((comp flatten seq) {:a [1 2] :b [3 4]})
(:b 3 4 :a 1 2)
so> (apply concat {:a [1 2] :b [3 4]})
(:b [3 4] :a [1 2])

Flatten将从键和值中删除结构,这可能不是您想要的。在某些用例中,您确实希望删除嵌套序列的结构,并且为此类情况编写了flatten。但是对于地图的解构,你通常希望保持内部序列不变。

答案 1 :(得分:4)

任何flatten都无法展平,它应该完整无损。在顶层,它没有。

(flatten 8)
()

(flatten {1 2, 3 4})
()

如果您认为自己已经提供了一个序列,但是您没有,那么您将获得提供空序列的效果。这是大多数核心职能部门要排除的断路器。例如,(str nil) => ""

flatten应该像这样工作:

(defn flatten [x]
  (if (sequential? x)
    ((fn flat [y] (if (sequential? y) (mapcat flat y) [y])) x)
    x))

(flatten 8)
;8

(flatten [{1 2, 3 4}])
;({1 2, 3 4})

(flatten [1 [2 [[3]] 4]])
;(1 2 3 4)

你可以找到Steve Miner这个here更快的懒惰版本。

答案 2 :(得分:2)

"可能"

的可能性

倾听那些说'#34;你可能做错了什么&#34;但也不要忘记他们说&#34;可能&#34;,因为这一切都取决于问题。< / p>

例如,如果你的任务是将地图展平,你可以在那里关心什么是关键值是什么,你只需要一个非结构化的序列,然后通过各种方式,使用展平(或apply concat )。

它引起怀疑的原因&#34;事实上,你有map开始,因此无论谁给你意味着一个&#34;关键价值&#34;配对结构,如果你展平它,你会失去意图,以及灵活性和清晰度。

请记住

如果您仍然不确定 map针对您的特定问题做什么,请记住for理解,因为您将拥有完全控制权在迭代它时如何处理地图:

创建一个向量?

;; can also be (apply vector {:a 34 :b 42}), but just to use "for" for all consistently

user=> (into [] (for [[k v] {:a 34 :b 42}] [k v]))
[[:a 34] [:b 42]]

创建另一张地图?

user=> (into {} (for [[k v] {:a 34 :b 42}] [k (inc v)]))
{:a 35, :b 43}

创建一个集合?

user=> (into #{} (for [[k v] {:a 34 :b 42}] [k v]))
#{[:a 34] [:b 42]}

反向键和值?

user=> (into {} (for [[k v] {:a 34 :b 42}] [v k]))
{34 :a, 42 :b}