2013-06-27 12 views
34

Jest to dla mnie pospolitym, powtarzalnym idiomem: filtrowanie tablicy za pomocą wyrażenia regularnego i zwracanie tablicy podrzędnej. Moje podejście nie wydaje się bardzo podobne do Rubiego (pochodzę z Javy). Kończę mając wiele metod, które wyglądają bardzo podobnie.Ruby: filter array by regex?

Co to jest idiomatyczny sposób Ruby, aby ulepszyć ten kod?

def get_all_gifs(items_) 
    output = Array.new 
    filter = /\.jpg$/ 
    items_.each do |item| 
    next if item =~ filter 
    output << item 
    end 
    output 
end 
+0

Jak się masz nazwy plików? Jeśli z dysku możesz je odfiltrować, gdy pobierzesz nazwy używając 'Dir.glob ('*. Jpe? G')' –

+0

Myślę, że prawie wszyscy źle zrozumieli moje pytanie (być może dlatego, że źle je zadałem). Przykład może być zbyt obciążony. Nie dotyczy to obrazów ani nazw plików ani rozszerzeń plików. Chodzi o filtrowanie tablic i lepszy język metod. – allanberry

Odpowiedz

55

Jeśli chcesz znaleźć wszystkie gify:

def get_all_gifs(files) 
    files.select{ |i| i[/\.gif$/] } 
end 

Jeśli chcesz znaleźć wszystkie JPEG:

def get_all_jpgs(files) 
    files.select{ |i| i[/\.jpe?g$/] } 
end 

ich trwania:

files = %w[foo.gif bar.jpg foo.jpeg bar.gif] 
get_all_gifs(files) # => ["foo.gif", "bar.gif"] 
get_all_jpgs(files) # => ["bar.jpg", "foo.jpeg"] 

Ale czekaj! Jest więcej!

Co jeśli chcesz pogrupować je wszystkim swoim rodzaju, potem wyciągać na podstawie rozszerzenia ?:

def get_all_images_by_type(files) 
    files.group_by{ |f| File.extname(f) } 
end 

Oto typy plików:

get_all_images_by_type(files).keys # => [".gif", ".jpg", ".jpeg"] 

Oto jak chwycić określone typy :

get_all_images_by_type(files) # => {".gif"=>["foo.gif", "bar.gif"], ".jpg"=>["bar.jpg"], ".jpeg"=>["foo.jpeg"]} 
get_all_images_by_type(files)['.gif'] # => ["foo.gif", "bar.gif"] 
get_all_images_by_type(files).values_at('.jpg', '.jpeg') # => [["bar.jpg"], ["foo.jpeg"]] 
15
$ cat foo.rb 
images = %w[foo.gif foo.png foo.jpg bar.jpeg moo.JPG] 
jpgs = images.select{|e| e =~ /\.jpe?g$/i} 
puts jpgs.inspect 

$ ruby foo.rb 
["foo.jpg", "bar.jpeg", "moo.JPG"] 

Zmiana do regexp jest tak, że można dopasować „JPEG” oprócz „jpg”, niezależnie od przypadku.

+1

Metoda "wybierz" jest tym, czego szukam tutaj (a raczej metodą "odrzucania", teraz, gdy ją znalazłem). Dzięki. – allanberry

18

Spójrz na Enumerable.grep, jest to bardzo skuteczny sposób znajdowania/filtrowania t miewa wszystko, co można przeliczyć.

+0

Działa to jak dickens. Prawdopodobnie skorzystam z tego od teraz, ale w wąskim sensie, metoda "wybierz" jest tym, o czym mówiłem w tym pytaniu. Dziękuję bardzo. – allanberry

+0

Tak, 'grep' jest wielki, częściowo dlatego, że używa' === 'do porównywania elementów odbiornika z argumentem' grep'. To pozwala napisać, na przykład, "[" abc "," bcd "," cbd "]. Grep (/. B. /) # => [" Abc "," cbd "]' i '[{a : 1}, 4, {b: 2}, "kapelusz"]. Grep (Hash) # => [{: a => 1}, {: b => 2}] '. –

3

Możemy przejść bez regex dla tego konkretnego problemu. Użyj String#end_with?

images = %w[foo.gif foo.png foo.jpg bar.jpeg moo.JPG] 
images.find_all{|e| e.end_with?(".jpg",".jpeg")} 
# => ["foo.jpg", "bar.jpeg"] 
9
images = %w[foo.gif foo.png foo.jpg bar.jpeg moo.JPG] 
images.grep(/.jpg/g) # => ["foo.jpg", "moo.JPG"] 
0
ta, tb = files.partition{|f| f[/(.*\.jpe*g)/]} 

ap ta 
[ 
    [0] "bar.jpg", 
    [1] "foo.jpeg" 
] 


ap tb 
[ 
    [0] "foo.gif", 
    [1] "bar.gif" 
] 

/Gucio