Компактный код Clojure для совпадений регулярных выражений и их положения в строке - PullRequest
10 голосов
/ 16 июля 2010

Стюарт Халлоуэй приводит пример

(re-seq #"\w+" "The quick brown fox")

как естественный метод поиска совпадений с регулярными выражениями в Clojure. В его книге эта конструкция противопоставлена ​​итерации по совпадению. Если бы все заботились о списке матчей, это было бы здорово. Тем не менее, что, если бы я хотел совпадений и их положение в строке? Есть ли лучший способ сделать это, который позволяет мне использовать существующую функциональность в java.util.regex с использованием чего-то вроде понимания последовательности по каждому индексу в исходной строке? Другими словами, хотелось бы напечатать что-то вроде

(re-seq-map # "[0-9] +" "3a1b2c1d")

, которая возвращает карту с ключами в качестве позиции и значениями в качестве совпадений, например,

{0 "3", 2 "1", 4 "2", 6 "1"}

Есть ли какая-то реализация этого в уже существующей библиотеке или я напишу это (не должно быть слишком много строк кода)?

Ответы [ 2 ]

10 голосов
/ 16 июля 2010

Вы можете получить нужные данные из объекта java.util.regex.Matcher.

user> (defn re-pos [re s]
        (loop [m (re-matcher re s)
               res {}]
          (if (.find m)
            (recur m (assoc res (.start m) (.group m)))
            res)))
#'user/re-pos
user> (re-pos #"\w+" "The quick brown fox")
{16 "fox", 10 "brown", 4 "quick", 0 "The"}
user> (re-pos #"[0-9]+" "3a1b2c1d")
{6 "1", 4 "2", 2 "1", 0 "3"}
1 голос
/ 13 января 2017

Вы можете применить любую функцию к объекту java.util.regex.Matcher и вернуть его результаты (аналогично решению Брайана, но без явного loop):

user=> (defn re-fun
         [re s fun]
         (let [matcher (re-matcher re s)]
           (take-while some? (repeatedly #(if (.find matcher) (fun matcher) nil)))))
#'user/re-fun

user=> (defn fun1 [m] (vector (.start m) (.end m)))
#'user/fun1

user=> (re-fun #"[0-9]+" "3a1b2c1d" fun1)
([0 1] [2 3] [4 5] [6 7])

user=> (defn re-seq-map
         [re s]
         (into {} (re-fun re s #(vector (.start %) (.group %)))))

user=> (re-seq-map #"[0-9]+" "3a1b2c1d")
{0 "3", 2 "1", 4 "2", 6 "1"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...