Tinus Wagner Tinus Wagner - 6 months ago 20
Ruby Question

Chaning Ruby regexp operators

I'm writing a filter program that reads a CSV file and excludes rows that are located in a cresent [sic] (

cres
), avenue (
ave
) or place (
pl
).

I can use simple regexp expressions to filter for one of the three, but I can't chain them using
&&
, nor do they function when I split them into three seperate [sic] filters.

Any ideas?

lines = []
i = 0

elements = []
element2 = []
output = []

file = File.open("./properties.csv", "r")

while (line = file.gets)
i += 1
# use split to break array up using commas
arr = line.split(',')
elements.push({ id: arr[0], streetAddress: arr[1], town: arr[2], valuationDate: arr[3], value: arr[4] })
end

file.close

# filter out AVE, CRES & PL

x = elements.select { |elements| elements[:streetAddress].downcase! !~ /pl/ && elements[:streetAddress].downcase! !~ /cres/ && elements[:streetAddress].downcase! !~ /ave/}

puts x

puts "#{x.length} houses that aren't in AVE's/CRES's/PL's"


Sample 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 Kamahi ST,WANAKA,1/1/2015,155000
5,1 Kapuka LANE,WANAKA,1/1/2015,149000
6,1 Mohua MEWS,WANAKA,1/1/2015,560000
7,1 Kakapo CT,WANAKA,1/1/2015,430000
8,1 Mt Gold PL,WANAKA,1/1/2015,1260000
9,1 Penrith Park DR,WANAKA,1/1/2015,1250000
10,1 ATHERTON PL,WANAKA,1/1/2015,650000
11,1 WAIMANA PL,WANAKA,1/1/2015,780000
12,1 ROTO PL,WANAKA,1/1/2015,1470000
13,1 Toms WAY,WANAKA,1/1/2015,2230000
14,1 MULBERRY LANE,WANAKA,1/1/2015,415000
15,1 Range View PL,WANAKA,1/1/2015,300000
16,1 Clearview ST,WANAKA,1/1/2015,1230000
17,1 Clutha PL,WANAKA,1/1/2015,700000
18,1 Centre CRES,WANAKA,1/1/2015,295000
19,1 Valley CRES,WANAKA,1/1/2015,790000
20,1 Edgewood PL,WANAKA,1/1/2015,365000
21,1 HUNTER CRES,WANAKA,1/1/2015,335000
22,1 KOWHAI DR,WANAKA,1/1/2015,480000
23,1 RIMU LANE,WANAKA,1/1/2015,465000
24,1 CHERRY CT,WANAKA,1/1/2015,495000
25,1 COLLINS ST,WANAKA,1/1/2015,520000

Answer

It's because of downcase! - it alters the receiver and it returns nil if no changes were made.

str = 'FOO'
str.downcase! #=> "foo"
str.downcase! #=> nil

Therefore, your second comparison becomes nil !~ /cres/ which is always true.

To fix your code, use downcase (without !):

elements[:streetAddress].downcase !~ /pl/

or add a i to your regular expression to make it case-insensitive:

elements[:streetAddress] !~ /pl/i

Furthermore, you can combine your regular expressions and use reject:

x = elements.reject { |e| e[:streetAddress] =~ /pl|cres|ave/i }