(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 условий:
- Если
v
пусто, просто создайте новый вектор с новымоценить и записать новое значение.Это необходимо, потому что поиск пустого вектора (следующее условие) приведет к исключению. - Если последнее значение
v
совпадает с новым значением, удалите его и запишите новое значение. - Если новое значение (
n
) совпадает с последним значением (p
), игнорируйте его.Это условие позволяет нам исключить значения, которые повторяются несколько раз. - Если ни одно из этих условий не выполняется, можно добавить значение:)