Clojure разделить список строк, накапливая результат

Я сожалею о нехватке точности в названии, но это может проиллюстрировать мое отсутствие опыта уловки.

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

Например, если у меня есть

[ "a" "bc" "def" "ghij" ]

и моя максимальная длина строки равна 4, я бы шел по списку, накапливая concat, до тех пор, пока накопленное значение len > 4, и затем запустил бы аккумулятор с нуля. Мой результат будет выглядеть так:

[ "abc" "def" "ghij" ]

Я не могу придумать правильное заклинание для partition-byи это сводит меня с ума. Я пытался сделать свой аккумулятор atom (но не могу понять, где reset!), но кроме этого, я не вижу, где / как отслеживать мою накопленную строку.

Заранее спасибо всем, кто помилует меня.

4 ответа

Решение
(defn catsize [limit strs]
  (reduce (fn [res s]
              (let [base (peek res)]
                (if (> (+ (.length ^String base) (.length ^String s)) limit)
                  (conj res s)
                  (conj (pop res) (str base s)))))
          (if (seq strs) [(first strs)] [])
          (rest strs)))

Вот мой взгляд на это:

(defn collapse [maxlen xs]
  (let [concats (take-while #(< (count %) maxlen) (reductions str xs))]
    (cons (last concats) (drop (count concats) xs))))
(collapse 4 ["a" "bc" "def" "ghij"])
;; => ("abc" "def" "ghij")

Это довольно близко. Я не уверен, почему у вас есть J в конце последней строки.

(sequence
 (comp
  (mapcat seq)
  (partition-all 3)
  (map clojure.string/join))
 ["a" "bc" "def" "ghij"]) => ("abc" "def" "ghi" "j")

Вот как я бы это сделал:

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test))

(def bound 4)

(defn catter [strings-in]
  (loop [merged-strs    []
         curr-merge     (first strings-in)
         remaining-strs (rest strings-in)]
   ;(newline) (spyx [merged-strs curr-merge remaining-strs])
    (if (empty? remaining-strs)
      (conj merged-strs curr-merge)
      (let          ; try using 'let-spy' instead
        [new-str   (first remaining-strs)
         new-merge (str curr-merge new-str)]
        (if (< (count new-merge) bound)
          (recur merged-strs new-merge (rest remaining-strs))
          (recur (conj merged-strs curr-merge) new-str (rest remaining-strs)))))))

(dotest
  (is=  ["abc" "def" "ghij"]     (catter ["a" "bc" "def" "ghij"]) )
  (is=  ["abc" "def" "ghij"]     (catter ["a" "b" "c" "def" "ghij"]) )
  (is=  ["abc" "def" "ghij"]     (catter ["a" "b" "c" "d" "ef" "ghij"]) )
  (is=  ["abc" "def" "ghij"]     (catter ["a" "bc" "d" "ef" "ghij"]) )
  (is=  ["abc" "def" "ghij"]     (catter ["a" "bc" "d" "e" "f" "ghij"]) )

  (is=  ["abc" "def" "gh" "ij"]  (catter ["abc" "d" "e" "f" "gh" "ij"]) )
  (is=  ["abc" "def" "ghi" "j"]  (catter ["abc" "d" "e" "f" "ghi" "j"]) )

  (is=  ["abcdef" "ghi" "j"]     (catter ["abcdef" "ghi" "j"]) )
  (is=  ["abcdef" "ghi" "j"]     (catter ["abcdef" "g" "h" "i" "j"]) )
)

Вам нужно будет добавить [tupelo "0.9.71"] спроектировать зависимости.


Обновить:

Если вы пользователь spy а также let-spyВы можете увидеть процесс, используемый алгоритмом для получения результата. Например:

(catter ["a" "b" "c" "d" "ef" "ghij"]) )   =>     ["abc" "def" "ghij"]     

-----------------------------------------------------------------------------
strings-in => ["a" "b" "c" "d" "ef" "ghij"]

[merged-strs curr-merge remaining-strs] => [[] "a" ("b" "c" "d" "ef" "ghij")]
new-str => "b"
new-merge => "ab"

[merged-strs curr-merge remaining-strs] => [[] "ab" ("c" "d" "ef" "ghij")]
new-str => "c"
new-merge => "abc"

[merged-strs curr-merge remaining-strs] => [[] "abc" ("d" "ef" "ghij")]
new-str => "d"
new-merge => "abcd"

[merged-strs curr-merge remaining-strs] => [["abc"] "d" ("ef" "ghij")]
new-str => "ef"
new-merge => "def"

[merged-strs curr-merge remaining-strs] => [["abc"] "def" ("ghij")]
new-str => "ghij"
new-merge => "defghij"

[merged-strs curr-merge remaining-strs] => [["abc" "def"] "ghij" ()]

Ran 2 tests containing 10 assertions.
0 failures, 0 errors.
Другие вопросы по тегам