簡體   English   中英

改變Ruby正則表達式運算符

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM