Функция библиотеки для сортировки по предикату - PullRequest
2 голосов
/ 08 января 2012

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

Например:

(let [[yays nays] (some-fn pred coll)] ... )

Более или менее, я ищу способ сортировки на основе предиката, а не выбрасывания (например, с filter или remove).

(Примечание: я знаю, что решение состоит в том, чтобы вызывать filter и remove для коллекции отдельно; я просто хотел бы знать, есть ли встроенная функция, которая может выполнить это более эффективно).

(Изменить: seq-utils/separate не считается более эффективным. Он оценивает предикат дважды для каждого элемента.)

Ответы [ 2 ]

3 голосов
/ 08 января 2012
1 голос
/ 08 января 2012

Если вам нужна максимальная производительность, вы захотите сделать это с помощью цикла / повторения, например:

(defn separate-by [pred coll]
     (loop [yays nil 
            nays nil 
            s (seq coll)]
       (if s
         (let [item (first s)
               test (pred item)]
           (if test
             (recur (conj yays item) nays (next s))
             (recur yays (conj nays item) (next s))))
         {:yays yays :nays nays})))

Причина, по которой это наиболее эффективно, заключается в том, что цикл / возврат позволяет вам итеративно создаватьдва списка вывода без каких-либо дополнительных выделений памяти (что может произойти, если вы обновили карту, например, повторно) или справочные издержки (что произошло бы, если бы вы использовали два атома для накопления результатов).

...