簡體   English   中英

Clojure - 合並兩個不同大小的向量

[英]Clojure - Merge two vectors of vectors different sizes

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

在輸出中,最后一項[jkl],L在沒有要合並的值時是一個常數值(因為它在第一個向量中沒有對應的項。我該怎么做?

PS:我是 Clojure 的新手,我很欣賞詳細的答案,以便我能更好地理解。 另外,對不起,如果這是一個微不足道的問題。

一般來說:

  • 將問題分解成可分離的部分
  • 給事物命名
  • 組成部分

因此,在這種情況下,您的問題可以分解為:

  • 將列表拆分為重疊和非重疊部分
  • 選擇每個重疊部分中最好的
  • 將非重疊部分填充到正確的長度
  • 將它們重新組合在一起。

因此,如果我對您的問題做出幾個假設,這里有一個分解並重新構建它的示例:

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]) 

還有更多的細節需要解決,比如當列表的列表長度相同時會發生什么,如果它們不是彼此的子集。 (是的,您也可以將其粉碎為“單襯”)

我會看看clojure.core.matrix (見這里); 它有一些很好的操作可以幫助你解決這個問題。

我通常會采用以下方法:

  1. 將集合填充到最長的集合的大小
  2. 映射它們,將集合的每個項目填充到最長的大小,映射項目以選擇結果值。

最好用代碼來說明:

首先讓我們組成一些輔助函數:

(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))

在回復:

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]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM