Идиоматически вставлять элементы между двумя элементами в последовательности, которые выполняют предикат? - PullRequest
5 голосов
/ 20 октября 2011

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

Ответы [ 3 ]

4 голосов
/ 20 октября 2011

Мой первый черновик будет что-то вроде

(defn insert-between [pred inter coll]
  (lazy-seq
   (when-let [s (seq coll)]
     (cons (first s)
           (mapcat (fn [[left right]]
                     (if (pred left right)
                       [inter right]
                       [right]))
                   (partition 2 1 s))))))


user> (insert-between < :less [1 6 7 4 3])
(1 :less 6 :less 7 4 3)

Кажется, работает, но я специально уродлив первый элемент в уродливой форме, и я думаю, что вы могли бы обойти это. В любом случае, решение может быть улучшено.

3 голосов
/ 20 октября 2011

Это обычная SO [clojure] гонка, которая предлагает самое краткое решение.:-) Обычно я не побеждаю, но многому учусь в процессе.В любом случае, вот мое решение:

(defn interpose-p [[a b & _ :as s] d p]
  (when-not (empty? s)
    (if (and (not (nil? b)) (p a b))
      (cons a (cons d (interpose-p (rest s) d p)))
      (cons a (interpose-p (rest s) d p)))))

(interpose-p [1 2 3 2 1 2 3] "," <) 

(1 "," 2 "," 3 2 1 "," 2 "," 3)

Обновление : Несмотря на то, что обсуждение окончено, здесь есть обновленное решение, учитывающее все комментарии.Это время должно быть достаточно сильным, если я правильно понимаю lazy-seq.Он спровоцирован ленивым обсуждением здесь .

(defn interpose-p
  [pred coll sep]
  (let [f (fn [c]
            (when-let [[a b & _ :as s] (seq c)]
              (if (and b (pred a b))
                (list* a sep (interpose-p pred (rest s) sep))
                (list* a (interpose-p pred (rest s) sep)))))]
    (lazy-seq (f coll))))
3 голосов
/ 20 октября 2011

Это моя попытка:

(defn interpose-predicated [pred in coll]
  (if (next coll)
    (->> coll
         (partition 2 1)
         (mapcat (comp next #(if (apply pred %) (interpose in %) %)))
         (cons (first coll)))
    coll))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...