2013-07-15 52 views
4

假設一個正則表達式Rubyish方式來自調用代碼,當前上下文的外面,然後到當前項目之外實施的另一調用傳遞:反轉正則表達式

["1", "2"].grep(/1/)  #=> ["1"] 

有一個簡單的,Rubyish的方式來實現以下行爲時正在進行調用?

["1", "2"].grep(/1/.negate) #=> ["2"] 

這種行爲類似於與!~操作者切換=~運算符。當然可以使用#select#reject,或者打開或子類Regexp。但是我很好奇Ruby中是否有一種方法可以用上面的方式否定正則表達式返回的匹配。另外,我不關心是否falseniltrue或者匹配的位置是否涉及完成此效果。

有一個theoretical question這是相關的,但超出了這裏的簡單考慮。


編輯:我得到的迭代器是Ruby中去過濾列表的一般方式,但人們可以俯瞰問題的制約。另外,我認爲正則表達式被顛倒的方式有很好的功能。我不認爲它是過度或過於聰明的一半;它是古老的面向對象編程和Ruby擅長的事情。

+2

雖然沒有語義明顯,如果你想想看,通過正則表達式來'split'「匹配」的所有那些非子-火柴。我不太熟悉Ruby,因此我無法寫出基於此的答案,但我相信別人可以。 –

+0

你的問題有點矛盾,因爲當你可以簡單地修改迭代器時,試圖用這種方式修改正則表達式不是Rubyish。我會說你想要達到什麼比Rubyish更尊貴。 – sawa

+0

@sawa - 原則上我不反對。但Ruby允許多種方式解決問題。在這種情況下,我想繼續使用不受控制的方法(不一定是'#grep'),例如,它可能不接受塊參數。 –

回答

3

你可以做這樣的事情:

class NegatedRegex < Regexp 
    def ===(other) 
    !super 
    end 
end 

class Regexp 
    def negate 
    NegatedRegex.new self 
    end 
end 

可能有其他的方法來重新實現,但grep的,這是不夠的:

["1", "2"].grep(/1/.negate) #=> ["2"] 
+0

沿着這些路線的東西也許是唯一的方法來做到這一點。如果Ruby中沒有內置的支持,我會接受這個答案(我得到的印象是沒有)。例如 –

+3

'String#scan',直接在MRI上調用'rb_reg_search'。如果不重新實現可能需要正則表達式的每種方法,則無法更改此行爲。 –

+5

儘管這很聰明,但它可能太聰明瞭,從現在開始,你會想要建立一個時間機器回來,並防止自己永遠無法做到這一點。 – tadman

6
["1", "2"].reject { |e| /1/ === e } 
+0

我喜歡這個怪異的,但你使用'#拒絕',我希望繼續使用'#grep'(或者其他一些我無法控制的方法)。 –

+0

爲什麼你反對使用正確的工具來完成這項工作? – tadman

+0

@tadman:我試圖在從我的控制中傳遞一個正則表達式到一個不受我控制的方法(不一定是'#grep')的限制內工作,就是這樣。我並不想變得困難。 –

1
arr=["1","2"] 
arr-arr.grep("1") # ["2"] 

:)

1

這可能是這樣做的一種方式

["1", "2", 3].select {|i| i !~ /1/ } 
=> ["2", 3] 
3

你可以做這兩個動作一氣呵成:

re = /1/ 
matches, non_matches = ["1", "2", "1", "3"].partition { |el| re =~ el } 

p matches  #=> ["1", "1"] 
p non_matches #=> ["2", "3"]