#clojure
Вопрос:
Мне очень нравится использовать contains?
, потому что это так кратко и читабельно. Я хочу посмотреть, содержит ли набор карт, которые имеют те же пары ключей и значений, что и пример, в котором также были другие пары значений ключей. Я почти уверен contains?
, что здесь это не сработает. Есть ли альтернатива? Может быть, мне придется его написать (я наконец-то вхожу в образ мышления!). Например, если бы у меня был
(def some-set #{{:foo "bar" :beep "boop"}{:foo "bar"} {:foo "bar" :hi "there"}})
каким был бы быстрый способ узнать, есть ли у него какие-либо карты, которые совпадают {:foo "bar" :one "two"}
:foo "bar"
?
Ответ №1:
Отредактировано: Помня, что карта представляет собой набор векторов ключ-значение, вот реализация предиката submap?
:
(defn submap?
"Returns true if subm is a submap of m, false otherwise."
[subm m]
(every? (fn [[k v]] (= (get m k ::not-found) v)) subm))
Этот предикат можно использовать для фильтрации любой коллекции:
(filter #(submap? {:a 1 :b 2} %) [{:a 1} {:a 1 :b 2 :c 3}])
=> ({:a 1, :b 2, :c 3})
Оригинальный ответ
Это решение работает, но медленнее, чем мой обновленный ответ, из-за построения (set m)
для больших m
(defn submap?
"Returns true if subm is a submap of m, false otherwise."
[subm m]
(let [kvs (set m)]
(every? kvs subm)))
Комментарии:
1. Спасибо вам за это! Я собираюсь попробовать это сейчас.
Ответ №2:
Общим способом было бы написать предикат, который проверяет, содержит ли карта другую карту. Это можно сделать, используя select-keys
только карту с определенными ключами; используя keys
карту для сравнения, а затем просто сравнивая результат, вы получите это.
(def maps #{{:foo "bar" :beep "boop"} {:foo "bar"} {:foo "bar" :hi "there"} {:foo "baz"}})
(defn submap?
[submap m]
(= (select-keys m (keys submap)) submap))
(println
(filter (partial submap? {:foo "bar"}) maps))
; → ({:foo bar, :beep boop} {:foo bar, :hi there} {:foo bar})
Тем не менее, это всего лишь простой последовательный поиск. Это не означает (и
, к сожалению, в ядре нет ничего, что могло бы помочь), что ваши карты находятся в наборе.
Также обратите внимание, что порядок результата не определен, так как порядок
наборов тоже.
Комментарии:
1. Классно! Раньше я думал, о… боже… Я должен написать это, но теперь я начинаю создавать свои собственные маленькие утилиты (со всей вашей помощью). Я также ценю предложение Алана о библиотеке. Немного того и другого будет ключевым моментом.
Ответ №3:
Вы можете найти множество предикатов такого рода и связанных с ними вспомогательных функций в библиотеке Тупело, в частности:
- подкапывание?
- субматч?
- дикий матч?
- дикий-субматч?
Это особенно полезно при написании модульных тестов. Например, вас могут интересовать только определенные поля, например :body
, при тестировании ответа веб-сервера, и вы хотите игнорировать другие поля, такие как IP-адрес или метка времени.
Модульные тесты показывают код в действии.
Комментарии:
1. Я много видел Тьюпело и собираюсь взглянуть на него сейчас. Спасибо вам также за то, что показали, где я могу видеть, как он используется… очень полезно!