Clojure: применение вложенного векторного формата к плоскому вектору

Например, у меня есть следующий вложенный вектор:

[[[0.582198689235419 -0.34713183143727 0.4685311493624731]
  [-0.38928013774079284 -0.5901700383677557 -0.37573234072157]
  [0.6716356761877877 -0.19645167952721243 -0.5700686091940252]]
 [[0.0027162308840597005 -0.4483592764429284 -0.4766278022217257 -0.2724018313051576]
  [-0.2765881229144672 -0.8030656496255356 -0.16159395457031567 -0.27432324260043084]
  [-0.6154630466545907 -0.60573539482247 0.4417814561800192 -0.5559788990464504]
  [0.6194560094536031 -0.3663074359460578 -0.5704311251195602 0.7194827876969362]]]

И у меня есть следующий плоский вектор:

(0.5366343712173423
 -0.816449781850872
 -0.16066485785704843
 0.9816561233924161
 -0.09646744313584676
 -0.2619662625757997
 -0.9946004265996822
 -0.14096299956754854
 0.579260850612288
 -0.827601452607939
 -0.24934665032374648
 -0.42272393175707873
 0.11239245249400165
 -0.29878238708035043
 -0.61522274672097
 0.8298721730401472
 0.5016214138116059
 0.11633537727916243
 -0.0631891708267196
 -0.26569217599364303
 0.20900664784109668
 0.2005869506108401
 -0.2658279978034501
 0.3383997403318165
 -0.09353513546647907)

Я хочу, чтобы плоский вектор был преобразован во вложенный вектор, который следует той же структуре, что и вложенный вектор, представленный выше. Есть ли основная функция в Clojure или библиотека, которая делает это? У меня есть некоторые идеи, как решить эту проблему, но все они кажутся очень и очень неэффективными, и эта операция будет использоваться с большими векторами.

Заранее большое спасибо.


person amherag    schedule 11.05.2016    source источник


Ответы (1)


Было интересно ответить на этот вопрос, потому что это один из очень немногих случаев, когда я думаю, что использование молнии делает вещи проще, а не сложнее. Идея состоит в том, чтобы просто сделать vector-zip из вложенного вектора, чтобы представить желаемую структуру, и многократно вызывать zip/next для него; всякий раз, когда мы добираемся до узла, который является листом, мы заменяем его значение следующим из входной последовательности.

Обратите внимание, что это предполагает, что во вложенной структуре ровно столько элементов, сколько в сглаженном списке; если это не так, вы, вероятно, получите какую-то ошибку, кто знает.

(require '[clojure.zip :as z])

(defn replace-values [structure values]
  (loop [z (z/vector-zip structure)
         values (seq values)]
    (cond (not values) (z/root z)
          (z/branch? z) (recur (z/next z) values)
          :else (recur (-> z
                           (z/replace (first values))
                           (z/next))
                       (next values)))))

user> (replace-values '[[[0.582198689235419 -0.34713183143727 0.4685311493624731]
                         [-0.38928013774079284 -0.5901700383677557 -0.37573234072157]
                         [0.6716356761877877 -0.19645167952721243 -0.5700686091940252]]
                        [[0.0027162308840597005 -0.4483592764429284 -0.4766278022217257 -0.2724018313051576]
                         [-0.2765881229144672 -0.8030656496255356 -0.16159395457031567 -0.27432324260043084]
                         [-0.6154630466545907 -0.60573539482247 0.4417814561800192 -0.5559788990464504]
                         [0.6194560094536031 -0.3663074359460578 -0.5704311251195602 0.7194827876969362]]]
                      '(0.5366343712173423
                        -0.816449781850872
                        -0.16066485785704843
                        0.9816561233924161
                        -0.09646744313584676
                        -0.2619662625757997
                        -0.9946004265996822
                        -0.14096299956754854
                        0.579260850612288
                        -0.827601452607939
                        -0.24934665032374648
                        -0.42272393175707873
                        0.11239245249400165
                        -0.29878238708035043
                        -0.61522274672097
                        0.8298721730401472
                        0.5016214138116059
                        0.11633537727916243
                        -0.0631891708267196
                        -0.26569217599364303
                        0.20900664784109668
                        0.2005869506108401
                        -0.2658279978034501
                        0.3383997403318165
                        -0.09353513546647907))

[[[0.5366343712173423 -0.816449781850872 -0.16066485785704843]
  [0.9816561233924161 -0.09646744313584676 -0.2619662625757997]
  [-0.9946004265996822 -0.14096299956754854 0.579260850612288]]
 [[-0.827601452607939 -0.24934665032374648 -0.42272393175707873 0.11239245249400165]
  [-0.29878238708035043 -0.61522274672097 0.8298721730401472 0.5016214138116059]
  [0.11633537727916243 -0.0631891708267196 -0.26569217599364303 0.20900664784109668]
  [0.2005869506108401 -0.2658279978034501 0.3383997403318165 -0.09353513546647907]]]
person amalloy    schedule 11.05.2016