我有一个功能
(defn my-fn [a b & args]
[a
(for [arg args]
(into [] (butlast arg)))
b])
如果我(my-fn [1 2] [3 4] [5 6 2] [7 8 3])
返回[[1 2] ([5 6] [7 8]) [3 4]]
我希望输出为[[1 2] [5 6] [7 8] [3 4]]
,但我无法弄清楚如何执行此操作
非常感谢任何帮助。
答案 0 :(得分:5)
我into
[a]
所有的映射值,最后是conj
b
。 E.g。
(defn my-fn [a b & args]
(-> [a]
(into (map (comp vec butlast) args))
(conj b)))
答案 1 :(得分:1)
以及另一个变体,使用引用和非引用拼接:
user> (defn my-fn2 [a b & args]
`[~a ~@(map (comp vec butlast) args) ~b])
;;=> #'user/my-fn2
user> (my-fn2 [1 2] [3 4] [5 6 2] [7 8 3])
;;=> [[1 2] [5 6] [7 8] [3 4]]
答案 2 :(得分:0)
这是一个解决方案:
(defn my-fn [a b & args]
(vec
(concat
[a]
(for [arg args]
(into [] (butlast arg)))
[b])))
(my-fn [1 2] [3 4] [5 6 2] [7 8 3])
=> [[1 2] [5 6] [7 8] [3 4]]
请注意,concat
会返回一个惰性列表,该列表适用于较大和/或更复杂的问题can cause a StackOverflowException。外部vec
将惰性列表转换为具体向量。这个例子没有必要,你可以根据需要删除它。
另外注意,concat
期望每个参数都是一个列表/向量,所以我将a
和b
包装成1个元素的向量。 for
的输出已经是(懒惰)列表。
由于conj
,cons
,concat
等行为可能有点不直观,您可能希望查看辅助函数glue
,{{1 },append
,&朋友in the Tupelo library。
假设我们有混合的标量&我们想要组合成单个向量的向量(或列表)。我们想要一个功能???给我们以下结果:
prepend
Clojure没有这方面的功能。相反,我们需要将所有标量包装到矢量中,然后使用胶水或连接:
(??? 1 2 3 [4 5 6] 7 8 9) => [1 2 3 4 5 6 7 8 9]
总是将标量值包装到矢量中只是为了将它们与偶然的矢量值组合起来可能不方便。相反,打开矢量值可能更方便,然后将结果与其他标量组合。我们可以做到with the ->vector
and unwrap
functions:
; can wrap individually or in groups
(glue [1 2 3] [4 5 6] [7 8 9]) => [1 2 3 4 5 6 7 8 9] ; could also use concat
(glue [1] [2] [3] [4 5 6] [7] [8] [9]) => [1 2 3 4 5 6 7 8 9] ; could also use concat
对于嵌套的(->vector 1 2 3 4 5 6 7 8 9) => [1 2 3 4 5 6 7 8 9]
(->vector 1 (unwrap [2 3 4 5 6 7 8]) 9) => [1 2 3 4 5 6 7 8 9]
调用,它也会递归工作:
unwrap
答案 3 :(得分:0)
您的for
语句会返回一个列表。
(defn my-fn [a b & args]
(->> [[a]
(map (comp vec butlast) args)
[b]]
(apply concat)
vec))
最终vec
将您的seq转换为矢量。
答案 4 :(得分:0)
你也可以这样解决:
null
此处(ns tst.clj.core
(:use clj.core tupelo.test)
(:require [tupelo.core :as t] ))
(t/refer-tupelo)
(defn my-fn [a b & args]
(lazy-gen
(yield a)
(yield-all (for [arg args]
(into [] (butlast arg))))
(yield b)))
(my-fn [1 2] [3 4] [5 6 2] [7 8 3]) => ([1 2] [5 6] [7 8] [3 4])
为"生成器函数"创建上下文,其中使用lazy-gen
和yield
函数将连续值添加到输出列表中。请注意,yield-all
函数类似于Clojure" unquote-splicing" operator yield-all
和" unwraps"它的序列进入输出流。
更简单的答案是深入了解原始解决方案的~@
部分,以应用for
输出点按:
yield
此版本的解决方案更贴近原始逻辑,
并避免(defn my-fn2 [a b & args]
(lazy-gen
(yield a)
(doseq [arg args]
(yield (butlast arg)))
(yield b)))
(my-fn2 [1 2] [3 4] [5 6 2] [7 8 3]) => ([1 2] (5 6) (7 8) [3 4])
函数将其结果包装成序列的意外复杂性,该序列与未包含在向量中的for
和a
值冲突。我们也不再需要原始函数的b
部分。
请注意,我们已将(into [] ...)
替换为for
,因为: