Нечувствительный к регистру фильтр в 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))
Другие вопросы по тегам