在这里,我再次面临Clojure的一些问题。我有两个向量向量。
[[a b c] [d e f] [g h i]]
和
[[a b] [d e] [g h] [j k]]
我想以这样的方式合并这两个:最终的矢量将是这样的:
[[a b c] [d e f] [g h i] [j k l]]
在输出中,最后一项[j k l],当没有要合并的值时,L是一个常数值(因为它在第一个向量中没有对应的项目。 我该怎么办呢?
P.S。:我是Clojure的新手,我很欣赏一个精心设计的答案,以便我能更好地理解。另外,对不起,如果这是一个微不足道的问题。
答案 0 :(得分:2)
一般来说:
因此,在这种情况下,您的问题可以分解为:
因此,如果我对您的问题做出一些假设,那就是将其分解并重新构建它的示例:
user> (def a '[[a b c] [d e f] [g h i]])
#'user/a
user> (def b '[[a b] [d e] [g h] [j k]])
#'user/b
创建一个函数来选择正确的重叠部分对。虽然你可以合并这些,但我选择了长度:
user> (defn longer-list [x y]
(if (> (count x) (count y))
x
y))
#'user/longer-list
制作一个功能,填写一个太短的列表
user> (defn pad-list [l min-len default-value]
(into l (take (- min-len (count l)) (repeat default-value))))
#'user/pad-list
创建一个使用这两个函数分割然后重新组合问题部分的函数:
user> (defn process-list [a b]
(let [a-len (count a)
b-len (count b)
longer-input (if (> a-len b-len)
a
b)
shorter-input (if (< a-len b-len)
a
b)]
(concat (map longer-list longer-input shorter-input)
(map #(pad-list % 3 'l) (drop (count shorter-input) longer-input)))))
#'user/process-list
然后测试它: - )
user> (process-list a b)
([a b c] [d e f] [g h i] [j k l])
还有更多细节需要解决,比如当列表列表长度相同时,以及它们不是彼此的子集时会发生什么。 (是的,你可以把它粉碎到一个&#34;一个班轮&#34;也是)
答案 1 :(得分:0)
我会看一下clojure.core.matrix
(见here);它有一些很好的操作,可以帮助你。
答案 2 :(得分:0)
我通常采用以下方法:
最好用代码来说明它:
首先让我们组成一些辅助函数:
(defn max-count [coll1 coll2] (max (count coll1) (count coll2)))
它的名字本身就说明了。
(defn fill-up-to [coll size] (take size (concat coll (repeat nil))))
这个用nil
填充集合到某个大小:
user> (fill-up-to [1 2 3] 10)
(1 2 3 nil nil nil nil nil nil nil)
现在合并功能:
(defn merge-colls [v1 v2 default-val]
(let [coll-len (max-count v1 v2)
comp-len (max-count (first v1) (first v2))]
(mapv (fn [comp1 comp2]
(mapv #(or %1 %2 default-val)
(fill-up-to comp1 comp-len)
(fill-up-to comp2 comp-len)))
(fill-up-to v1 coll-len)
(fill-up-to v2 coll-len))))
外部mapv
对从初始参数填充的集合进行操作,这些参数填充到最长参数(coll-len
)的长度,因此在问题的上下文中将是:
(mapv some-fn [[a b c] [d e f] [g h i] nil]]
[[a b] [d e] [g h] [j k]])
内部mapv对内部向量进行操作,填充到comp-len
(在本例中为3):
(mapv #(or %1 %2 default-val) '[a b c] '[d e nil])
...
(mapv #(or %1 %2 default-val) '[nil nil nil] '[j k nil])
让我们测试一下:
user> (let [v1 '[[a b c] [d e f] [g h i]]
v2 '[[a b] [d e] [g h] [j k]]]
(merge-colls v1 v2 'l))
[[a b c] [d e f] [g h i] [j k l]]
好吧,它就像我们想要的那样有效。
现在,如果您查看merge-colls
,您可能会注意到模式的重复:
(mapv some-fn (fill-up-to coll1 size)
(fill-up-to coll2 size))
我们可以通过将此模式移到函数中来消除重复:
(defn mapv-equalizing [map-fn size coll1 coll2]
(mapv map-fn (fill-up-to coll1 size) (fill-up-to coll2 size)))
并重写我们的合并:
(defn merge-colls [v1 v2 default-val]
(let [coll-len (max-count v1 v2)
comp-len (max-count (first v1) (first v2))]
(mapv-equalizing (fn [comp1 comp2]
(mapv-equalizing #(or %1 %2 default-val)
comp-len comp1 comp2))
coll-len v1 v2)))
试验:
user> (let [v1 '[[a b c] [d e f] [g h i]]
v2 '[[a b] [d e] [g h] [j k]]]
(merge-colls v1 v2 'l))
[[a b c] [d e f] [g h i] [j k l]]
确定。现在我们可以通过删除集合大小绑定来缩短它,因为我们只需要这些值:
(defn merge-colls [v1 v2 default-val]
(mapv-equalizing
(partial mapv-equalizing
#(or %1 %2 default-val)
(max-count (first v1) (first v2)))
(max-count v1 v2) v1 v2))
在repl中:
user> (let [v1 '[[a b c] [d e f] [g h i]]
v2 '[[a b] [d e] [g h] [j k]]]
(merge-colls v1 v2 'l))
[[a b c] [d e f] [g h i] [j k l]]