Как сравнить значения последовательных элементов в векторе для фильтрации? - PullRequest
0 голосов
/ 14 февраля 2019

Мне нужно отфильтровать данный вектор так, чтобы выходные данные содержали только те элементы, которые не являются дубликатами непосредственного соседа.

Example : I/P -> [1 1 3 2 2 4 5 5]
          O/P -> [3 4]

Ответы [ 7 ]

0 голосов
/ 15 февраля 2019

Строя его более или менее с нуля, вы можете получить деструктурирование для выполнения большей части работы:

(defn no-dupes [coll]
  (when-let [[x & [y & ys :as xs]] (seq coll)]
    (if xs
      (if (= x y)
        (recur (drop-while #(= x %) ys))
        (lazy-seq (cons x (no-dupes xs))))
      (list x))))

Сказав это, я допустил две ошибки в этих нескольких строках, тогда как Ответ Алана Маллоя является абсолютно правильным.


Это быстрее, чем у аккуратной версии датчика dpassen ?

Да.По словам Критерия, это примерно в три раза быстрее: около 500 наносекунд по сравнению с 1,5 микросекундами для короткого примера.

0 голосов
/ 15 февраля 2019

Использование преобразователей, таких как решение @ amitr, но IMHO, немного чище:

(def isolate
  (comp
   (partition-by identity)
   (remove next)
   cat))

Затем его можно использовать с sequence, into, какой бы функцией приема преобразователя вы ни пожелали.

0 голосов
/ 15 февраля 2019

Это та же логика, что и в ответе @ amalloy, но она использует transducers вместо макроса потока (->>).

(defn isolate [coll]
  (transduce
   (comp
   (partition-by identity)
   (remove next)
   (map first))
  conj coll))

Она должна быть более эффективной, по крайней мере для большихcollection.

Разделы partition-by identity сопоставляются с подсписками идентичных элементов.remove next удаляет все подсписки, чей next не равен nil (т. Е. Они имеют более одного элемента).Последний map first берет первый элемент каждого подсписка, таким образом, сводя список списков к списку элементов.

Просто запустите каждый из шагов отдельно, чтобы увидеть, как он работает.

0 голосов
/ 15 февраля 2019

Еще один способ сделать это:

(defn remove-consecutive-duplicates [inp]
    (let [intm (into [] (partition-by identity inp))]
             (reduce (fn [acc n]
                (if (= 1 (count n))
                  (conj acc n)
                  acc ))
              [] intm)))

Обратите внимание, что дедупликация не дает желаемого результата.

0 голосов
/ 15 февраля 2019
(defn isolated [coll]
  (->> coll
       (partition-by identity)
       (remove next)
       (map first)))
0 голосов
/ 15 февраля 2019
(def data-1 [1 1 3 2 2 4 5 5])

(def data-2 [1 1 3 2 2 4 5 5 2 5 5])

(defn reducer [[v p] n]
  (cond
    (empty? v) [[n] n]
    (= (peek v) n) [(pop v) n]
    (= n p) [v n]
    :else [(conj v n) n]))

(first (reduce reducer [[] nil] data-1))
;[3 4]

(first (reduce reducer [[] nil] data-2))
;[3 4 2]

Обратите внимание, что это решение также охватывает случаи, когда существует более 2 одинаковых смежных значений, таких как:

(def data-3 [1 1 3 2 2 2 4 5 5 2 5 5])
;[3 4 2]

Вся тяжелая работа выполняется в функции-восстановителе.

Мысленно я всегда отмечаю первый параметр reduce как «аккумулятор», а второй как «новое значение».

В этом случае аккумулятор должен состоять из двух частей: векторачто вы создаете и последний номер видел.(Обратите внимание, что если вы ожидаете, что дубликаты будут встречаться только в парах, последнее увиденное число необязательно.)

Таким образом, [v p] является частью аккумулятора "редуктора" - v - это вектор, который выp - это предыдущее увиденное значение.Параметр n является «новым значением».

Объяснение 4 условий:

  1. Если v пусто, просто создайте новый вектор с новымоценить и записать новое значение.Это необходимо, потому что поиск пустого вектора (следующее условие) приведет к исключению.
  2. Если последнее значение v совпадает с новым значением, удалите его и запишите новое значение.
  3. Если новое значение (n) совпадает с последним значением (p), игнорируйте его.Это условие позволяет нам исключить значения, которые повторяются несколько раз.
  4. Если ни одно из этих условий не выполняется, можно добавить значение:)
0 голосов
/ 15 февраля 2019

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

(defn lonely? 
  "Return the ith element of v if it doesn't have a matching neighbor"
  [i v]
  (when (cond
          (zero? i) (not= (v 0) (v 1))
          (= i (- (count v) 1)) (not= (v i) (v (- i 1)))
          :else (and (not= (v i) (v (- i 1)))
                     (not= (v i) (v (+ i 1)))))
    (v i)))

> (def v [1 1 3 2 2 4 5 5])

> (keep #(lonely? % v) (range (count v)))
(3 4)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...