2010-07-16 14 views
10

Stuart Halloway konumlarını Clojure içinde regex maçları eşleşmeleri bulmak için doğal yöntem olarak ömeğiKompakt Clojure düzenli ifade maçları için kod ve dize

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

verir. Kitabında bu yapı bir eşleştirici üzerinde yineleme ile karşıttır. Eğer ilgili herkesin bir kibrit listesi varsa bu harika olurdu. Bununla birlikte, ne istersem ve dizideki pozisyonlarını istersem? Bunu yapmak, java.util.regex'deki mevcut işlevsellikten, orijinal dizideki her dizinin üzerinde bir dizi anlama gibi bir şeye başvurmaktan yararlanmamı sağlayan daha iyi bir yol var mı? Başka bir deyişle, bir gibi bir şey yazmak için istiyorum

(yeniden seq-haritası # "[0-9] +" "3a1b2c1d") olarak tuşlarıyla bir harita dönecekti

maçlar gibi pozisyon ve değerler

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

bir kaybolmamış kütüphanede bunun bazı uygulama zaten var mı yoksa bunu (kod may hatları da olmamalı) yazacak?

cevap

10

java.util.regex.Matcher nesnesinden istediğiniz verileri getirebilirsiniz.

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"} 
+0

teşekkürler Brian. Belki re-rex kütüphanesinde yerini bulmak gerekir. –

+0

Bu konuda biraz problemim var. (yeniden "ATAT" "GATATATGCATATACTT"), {9 "ATAT", 3 "ATAT", 1 "ATAT"} döndürmeli, ancak {9 "ATAT", 1 "ATAT"} döndürür. – boucekv

+0

Çakışan eşleşmeleri saymak isterseniz, normal ifadeyi biraz değiştirin: (yeniden konum # "(? = (ATAT))" "GATATATGCATATACTT"), {9 "", 3 "", 1 ""} döndürür. Eşleşen metni geri almak isterseniz, (.group m) yerine (.group m 1) yapmanız gerekir. –

1

Sen (ama açık loop olmadan, Brian'ın çözümüne simmilar) java.util.regex.Matcher nesnesine herhangi bir işlev uygulamak ve sonuçlarını döndürebilir:

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"}