Самый простой способ поиска записей в Clojure

#clojure

#clojure

Вопрос:

У меня есть карта в Clojure, что-то вроде этого:

 (def stuff #{

        {:a "help" :b "goodbye"}
        {:c "help2" :b "goodbye"}
        {:a "steve" :b "goodbye"}
        {:c "hello2" :b "sue"}
    })
  

: и я хочу обеспечить поиск таким образом, чтобы:

 (search stuff "help")
  

: вернул бы :

  #{
    {:a "help" :b "goodbye"}
    {:c "help2" :b "goodbye"}
}
  

: Какой самый простой способ сделать это?

Ответ №1:

 user=> (defn search [s q] (select #(some (partial re-find (re-pattern q)) (vals %)) s))
#'user/search
user=> (search stuff "help")
#{{:a "help", :b "goodbye"} {:c "help2", :b "goodbye"}}
  

Это делает свое дело.

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

1. Блестяще! Ты звезда. Это сработало в первый раз. (PS. Я также ценю, что вы действительно протестировали свой ответ перед публикацией) 🙂

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

3. Работает не так, как ожидалось: также возвращает ‘records’, где слово «help» также присутствует в качестве значения :b .

4. @Laurent — в защиту Rayne я хотел, чтобы он возвращал записи, когда слово «help» имело значение:b

5. @Laurent Это то, чего он хотел. Иди напиши что-нибудь против часовой стрелки или что-то в этом роде и оставь меня в покое. ;p

Ответ №2:

Полнотекстовый поиск — это другая тема, но если вы можете работать с регулярными выражениями, я бы использовал что-то вроде:

 (defn match [re e]
    (re-find re (:a e))

(defn search [re m]
    (into #{} (filter (partial match re) m)))
  

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

1. Я не могу заставить это работать. Когда я делаю это (поиск материала «справка»), он возвращает все четыре записи. В любом случае спасибо за попытку

Ответ №3:

(filter (comp #{"help"} :a) stuff) : свежесоставленная функция сначала вызывает :a целевой объект, затем вызывает #{"help"} результат: это возвращает истинное значение, если :a атрибут является точным "help" .

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

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

1. Спасибо. Я ищу что-то, что может выполнять поиск по нескольким ключам, хотя

2. Я также сделал то, что сказал, и просмотрел все макросы reader, но я не смог найти никаких макросов, которые могли бы преобразовать это в set. В любом случае спасибо за советы

3. Да? Функция set делает это. Зачем вам искать макрос reader?

4. Извините, возможно, я неправильно понял, как вы упомянули об использовании reader в ответе.

5. «Читатель» — это вы: в данный момент вы читаете этот ответ. «Оставить что-то в качестве упражнения для читателя» — это английская идиома, которую вы, возможно, пропустили. Это часто встречается в учебниках, что означает: «X можно выполнить, но это займет много места в книге, и вам все равно может понравиться делать это самостоятельно». Это тоже часто звучит как шутка: «X можно сделать, но я слишком ленив, чтобы это делать, так что сделай это сам».