как написать преобразователь, имитирующий поведение `lrem` для redis - PullRequest
1 голос
/ 28 февраля 2020

lrem - это команда, которая принимает n и значение, удаляя первые n элементы этого значения из списка.

Как можно написать что-то подобное, используя преобразователи:

(lrem [:a :b :c :b :a] 1 :b) 
=> [:a :c :b :a]

(lrem [:a :b :c :b :a] 2 :b) 
=> [:a :c :a]

Я хотел написать что-то более простое, чем это:

(loop [acc 0
       output [] 
       [x & more :as arr] arr]
  (cond (empty? arr) output
        (= count acc) (vec (concat output arr))
        (= value x) (recur (inc acc) output more)
        :else (recur acc (conj output x) more)))

1 Ответ

3 голосов
/ 28 февраля 2020

Это можно сделать, комбинируя подход таких преобразователей, как filter и distinct, потому что ваш преобразователь должен сделать что-то похожее на оба из них:

  1. Удалить элементы из последовательности, такие как filter
  2. Узнайте, сколько элементов было удалено, чтобы они могли остановиться. distinct аналогичен тем, что должен помнить каждое значение, которое видит.

    (defn lrem [n pred]
      (fn [rf]
        (let [removed (volatile! 0)] ;; keep count of removals
          (fn
            ([] (rf))
            ([result] (rf result))
            ([result input]
             (if (and (< @removed n) (pred input))
               (do (vswap! removed inc) ;; increment removal count
                   result)
               (rf result input)))))))
    
    (into []
          (lrem 3 pos?)
          (range 10))
    ;=> [0 4 5 6 7 8 9]
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...