Vector 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

在这里,我再次面临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]]