Vector Clojure-合并两个大小不同的向量
在这里,我再次面临Clojure的一些问题。我有两个向量Vector Clojure-合并两个大小不同的向量,vector,clojure,functional-programming,Vector,Clojure,Functional Programming,在这里,我再次面临Clojure的一些问题。我有两个向量 [[a b c] [d e f] [g h i]] 及 我想把这两个合并,最终的向量是这样的: [[a b c] [d e f] [g h i] [j k l]] 在输出中,最后一项[j k l],当没有要合并的值时,l是一个常数值(因为它在第一个向量中没有对应的项)。 我怎么能做这样的事 注:我是Clojure的新手,我很欣赏一个详尽的答案,这样我才能更好地理解。另外,如果这是一个微不足道的问题,我也很抱歉。我想看看Clojure
[[a b c] [d e f] [g h i]]
及
我想把这两个合并,最终的向量是这样的:
[[a b c] [d e f] [g h i] [j k l]]
在输出中,最后一项[j k l],当没有要合并的值时,l是一个常数值(因为它在第一个向量中没有对应的项)。
我怎么能做这样的事
注:我是Clojure的新手,我很欣赏一个详尽的答案,这样我才能更好地理解。另外,如果这是一个微不足道的问题,我也很抱歉。我想看看
Clojure.core.matrix
(请参阅);它有一些很好的操作,可以帮助您解决这个问题。一般来说:
- 把问题分解成可分离的部分
- 给事物命名
- 组成部分
- 将列表拆分为重叠部分和非重叠部分
- 选择每个重叠部分中的最佳部分
- 将非重叠部分填充到正确的长度
- 将它们重新组合在一起
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
还有更多细节需要解决,比如当列表的列表长度相同时会发生什么,如果它们不是彼此的子集(是的,您也可以将其分解为“一行”)我通常会采用以下方法:
(defn max-count [coll1 coll2] (max (count coll1) (count coll2)))
它的名字不言而喻
(defn fill-up-to [coll size] (take size (concat coll (repeat nil))))
这一个用nil
s填充集合,直到达到一定大小:
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))))
(defn mapv-equalizing [map-fn size coll1 coll2]
(mapv map-fn (fill-up-to coll1 size) (fill-up-to coll2 size)))
外部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在内部向量上运行,填充至组件(本例中为3):
让我们测试一下:
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]]
好的,它能正常工作
现在,如果您查看合并colls
,您可能会注意到模式的重复:
(mapv some-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 (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))))
(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)))
测试:
好的。现在我们可以通过删除集合大小绑定来缩短它,因为我们只需要这些值一次:
(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))
答复:
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]]
如果分量向量不匹配,比如说:[[ab]]
和[[cde]]]
,会发生什么情况?
(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))
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]]