[英]Chaning Ruby regexp operators
我正在編寫一個過濾程序,該程序讀取包含地址數據的CSV文件,並排除位於月牙(cres),大道(ave)或地點(pl)中的行。
這是一些示例輸入:
data = <<CSV
ID,Street address,Town,Valuation date,Value
1,1 Northburn RD,WANAKA,1/1/2015,280000
2,1 Mount Ida PL,WANAKA,1/1/2015,280000
3,1 Mount Linton AVE,WANAKA,1/1/2015,780000
4,1 Centre CRES,WANAKA,1/1/2015,295000
CSV
require 'csv'
elements = []
CSV.parse(data, headers: true, header_converters: :symbol) do |row|
elements << row.to_h
end
elements
#=> [
# {:id=>"1", :street_address=>"1 Northburn RD", :town=>"WANAKA", :valuation_date=>"1/1/2015", :value=>"280000"},
# {:id=>"2", :street_address=>"1 Mount Ida PL", :town=>"WANAKA", :valuation_date=>"1/1/2015", :value=>"280000"},
# {:id=>"3", :street_address=>"1 Mount Linton AVE", :town=>"WANAKA", :valuation_date=>"1/1/2015", :value=>"780000"},
# {:id=>"4", :street_address=>"1 Centre CRES", :town=>"WANAKA", :valuation_date=>"1/1/2015", :value=>"295000"}
# ]
我可以使用簡單的正則表達式來過濾以下三個之一,即/pl/
, /cres/
和/ave/
,但是我不能使用&&
鏈接它們:(當我將它們分成三個單獨的“過濾器”)
elements.select { |e| e[:street_address].downcase! !~ /pl/ && e[:street_address].downcase! !~ /cres/ && e[:street_address].downcase! !~ /ave/ }
#=> [
# {:id=>"1", :street_address=>"1 northburn rd", :town=>"WANAKA", :valuation_date=>"1/1/2015", :value=>"280000"},
# {:id=>"3", :street_address=>"1 mount linton ave", :town=>"WANAKA", :valuation_date=>"1/1/2015", :value=>"780000"},
# {:id=>"4", :street_address=>"1 centre cres", :town=>"WANAKA", :valuation_date=>"1/1/2015", :value=>"295000"}
# ]
這將按預期過濾出條目2,但不會過濾出條目3和4。
有什么想法我想念的嗎?
這是因為downcase!
-它更改接收器,如果未進行任何更改,則返回nil
。
str = 'FOO'
str.downcase! #=> "foo"
str.downcase! #=> nil
因此,您的第二個比較變為nil !~ /cres/
,這始終是true
。
要修復代碼,請使用downcase
(不帶!
):
elements[:streetAddress].downcase !~ /pl/
或在正則表達式中添加i
以使其不區分大小寫:
elements[:streetAddress] !~ /pl/i
此外,您可以結合使用正則表達式並使用reject
:
elements.reject { |e| e[:streetAddress] =~ /pl|cres|ave/i }
要僅匹配以“ pl”,“ cres”或“ ave” 結尾的字符串,請使用適當的錨 ,例如/(pl|cres|ave)$/i
如果要基於條件從數組中刪除元素,慣用的方法可能是使用Array#delete_if
IMO,當您已經知道接受哪些值時,請盡量不要使用正則表達式。 正則表達式擅長模式匹配(檢查電子郵件有效性等),但是它們的使用不應走得更遠。
假設RD,CRES,AVE始終位於最后,這是可行的:
x = elements.delete_if do |el|
['pl', 'cres', 'ave'].include?(el[:streetAddress].downcase.split.last)
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.