Clojure:对嵌套序列进行半展平

Chu*_*ucK 45 clojure sequence

我有一个嵌入的矢量列表的列表,看起来像:

(([1 2]) ([3 4] [5 6]) ([7 8]))

我所知道的并不理想.我想把它弄平([1 2] [3 4] [5 6] [7 8]).

flatten不起作用:它给了我(1 2 3 4 5 6 7 8).

我该怎么做呢?我想我需要根据每个列表项的内容创建一个新列表,而不是项目,而这部分我无法从文档中找到如何做.

nic*_*kik 60

如果您只想将其展平一级,则可以使用 concat

(apply concat '(([1 2]) ([3 4] [5 6]) ([7 8])))
=> ([1 2] [3 4] [5 6] [7 8])
Run Code Online (Sandbox Code Playgroud)


ama*_*loy 27

要将列表列表转换为包含每个子列表元素的单个列表,您需要apply concat像nickik建议的那样.

但是,通常有一个更好的解决方案:不要生成列表列表!例如,让我们假设你有一个函数get-names-for,它接受一个符号并返回一个你可以称之为符号的所有很酷的东西的列表:

(get-names-for '+) => (plus add cross junction)
Run Code Online (Sandbox Code Playgroud)

如果您想获得某些符号列表的所有名称,您可以尝试

(map get-names-for '[+ /]) 
=> ((plus add cross junction) (slash divide stroke))
Run Code Online (Sandbox Code Playgroud)

但这会导致您遇到的问题.你可以将它们粘在一起apply concat,但更好的方法是使用mapcat而不是map开头:

(mapcat get-names-for '[+ /]) 
=> (plus add cross junction slash divide stroke)
Run Code Online (Sandbox Code Playgroud)


Dav*_*nor 8

代码flatten很短:

(defn flatten
  [x]
  (filter (complement sequential?)
    (rest (tree-seq sequential? seq x))))
Run Code Online (Sandbox Code Playgroud)

它用于tree-seq遍历数据结构并返回原子序列.由于我们需要所有底层序列,我们可以像这样修改它:

(defn almost-flatten
  [x]
  (filter #(and (sequential? %) (not-any? sequential? %))
    (rest (tree-seq #(and (sequential? %) (some sequential? %)) seq x))))
Run Code Online (Sandbox Code Playgroud)

所以我们返回所有不包含序列的序列.