Нечувствительный к регистру фильтр в Clojure / ClojureScript
У меня есть эта функция:
(defn list-data [alist filter-text]
(filter (fn [x] (if (nil? filter-text) true
(> (.indexOf x filter-text) -1))) alist))
(list-data ["Lion" "Zebra" "Buffalo" "Antelope"] "a")
;=> ("Zebra" "Buffalo")
Есть ли более идиоматический способ написания этой функции и уважать тот факт, что я не хочу чувствительный к регистру фильтр, то есть мне бы хотелось, чтобы (list-data ["Lion" "Zebra" "Buffalo" "Antelope"] "a")
возвращает следующее:
;=> ("Zebra" "Buffalo" "Antelope")
Спасибо!
(Это должно было бы работать в .cljs
файл)
2 ответа
В самой Clojure вы обычно делаете это с помощью регулярного выражения. В регулярных выражениях Java вы можете сделать это, задав флаг нечувствительности к регистру для совпадения, которое вы хотите сделать, или в начале регулярного выражения для глобальной нечувствительности к регистру:
(filter #(re-find #"(?i)a" %)
["Lion" "Zebra" "Buffalo" "Antelope"])
Регулярные выражения в чистом Javascript поддерживают только глобальные флаги. Они задаются в виде строки как второй параметр для конструктора регулярных выражений:
(filter #(re-find (js/RegExp. "a" "i") %)
["Lion" "Zebra" "Buffalo" "Antelope"])
Однако для удобства и сохранения схожести регулярных выражений между Java и Javascript средство чтения Clojurescript переводит глобальные флаги стиля java (те, что находятся в начале регулярного выражения) в их глобальный эквивалент Javascript.
Так что первый пример работает и в Clojurescript. Имейте в виду, что неглобальные флаги не будут работать в Clojurescript, где они будут работать в Clojure.
(defn list-data [alist filter-text]
(if-let [filter-text (some-> filter-text not-empty .toLowerCase)]
(filter #(-> %
.toLowerCase
(.indexOf filter-text)
(not= -1))
alist)
alist))