Возврат дубликатов в последовательности

#clojure #duplicates #sequence

#clojure #дубликаты #последовательность

Вопрос:

Лучшее, что я мог придумать, было:

 (defn dups [seq]
  (map (fn [[id freq]] id) 
       (filter (fn [[id freq]] (> freq 1))
               (frequencies seq))))
  

Есть ли более краткий способ?

Комментарии:

1. Мне нравится ваше решение, но я бы просто заменил (fn [[id freq]] id) функцией key.

Ответ №1:

Используйте понимание списка:

 (defn dups [seq]
  (for [[id freq] (frequencies seq)  ;; get the frequencies, destructure
        :when (> freq 1)]            ;; this is the filter condition
   id))                              ;; just need the id, not the frequency
  

Ответ №2:

 (map key (remove (comp #{1} val) 
                 (frequencies seq)))
  

Комментарии:

1. Можете ли вы объяснить, что делает (comp #{1} val)? Спасибо.

2. (comp #{1} val) в основном означает (fn [x] (#{1} (значение x))) — в основном, он проверяет, равно ли значение аргумента 1 (если он содержится в наборе, содержащем число 1). значение здесь — это количество в паре частот.

Ответ №3:

Если вы хотите найти дубликаты на основе какого-либо свойства элементов в списке (т. Е. это список карт или список записей / объектов Java)

 (defn dups-with-function
  [seq f]
  (->> seq
       (group-by f)
       ; filter out map entries where its value has only 1 item 
       (remove #(= 1 (count (val %))))))

(let [seq [{:attribute    :one
            :other-things :bob}
           {:attribute    :one
            :other-things :smith}
           {:attribute    :two
            :other-things :blah}]]
  (dups-with-function seq :attribute))
  

выводит:

  ([:one
   [{:attribute :one, :other-things :bob}
    {:attribute :one, :other-things :smith}]])
  

Если у вас есть список объектов Java, и вы хотите найти все объекты с повторяющимися именами:

 (dups-with-function my-list #(.getFirstName %))
  

Комментарии:

1. Спасибо, что добавили свой ответ на мой вопрос: «Возврат дубликатов по клавише x в последовательности карт» 😉

Ответ №4:

Один элемент с минимальным фильтром и частотами, который выполняет работу:

 (filter #(< 1 ((frequencies col) %)) col)
  

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

 (let [ freqs (frequencies col) ]
  (filter #(< 1 (freqs %)) col))
  

Комментарии:

1. Не могли бы вы любезно объяснить, как / почему это помогает компилятору?

2. Помещая вычисление частот в предложение let лексического контекста, вы сначала принудительно вычисляете один раз, а не для каждого элемента в коллекции (можно надеяться, что компилятор сможет обнаружить и избежать).

Ответ №5:

some является идеальной функцией для этого.

 (defn dups [coll]
  (some (fn [[k v]] (when (< 1 v) k))
    (frequencies coll)))
  

Однако, по сути, это делает то же самое, что и понимание списка.