2013-06-27 32 views
34

Đây là một thành ngữ lặp đi lặp lại phổ biến cho tôi: lọc một mảng bằng cách sử dụng cụm từ thông dụng và trả về một mảng phụ. Cách tiếp cận của tôi dường như không giống Ruby (tôi đến từ Java). Tôi kết thúc có nhiều phương pháp trông rất giống thế này.Ruby: mảng lọc theo regex?

Cách thành ngữ Ruby để cải thiện mã này là gì?

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

How are you nhận được tên tập tin? Nếu từ đĩa bạn có thể lọc chúng khi bạn lấy tên bằng cách sử dụng 'Dir.glob ('*. Jpe? G')' –

+0

Tôi nghĩ hầu hết mọi người đều hiểu nhầm câu hỏi của tôi (có lẽ vì tôi đã hỏi nó rất tệ). Ví dụ có thể quá tải. Đây không phải là về hình ảnh hoặc tên tệp hoặc phần mở rộng tệp. Đó là về lọc mảng, và một thành ngữ tốt hơn cho các phương pháp để làm điều đó. – allanberry

Trả lời

55

Nếu bạn muốn tìm tất cả gif:

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

Nếu bạn muốn tìm tất cả JPEG:

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

Chạy họ:

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"] 

Nhưng chờ đợi! Còn nữa!

gì nếu bạn muốn để nhóm chúng lại tất cả theo loại của họ, sau đó giải nén dựa trên phần mở rộng ?:

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

Dưới đây là các loại tập tin:

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

Dưới đây là làm thế nào để lấy các loại cụ thể :

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"] 

Sự thay đổi để regexp của bạn là để bạn có thể kết hợp "jpeg", thêm vào "jpg" bất kể trường hợp.

+1

Phương pháp "chọn" là những gì tôi đang tìm kiếm ở đây (hoặc đúng hơn là phương pháp "từ chối", bây giờ tôi đã tìm thấy nó). Cảm ơn. – allanberry

18

Hãy xem Enumerable.grep, đây là cách tìm kiếm/lọc rất mạnh hings trong bất cứ điều gì enumerable.

+0

Điều này hoạt động giống như dickens. Tôi có thể sẽ sử dụng điều này từ bây giờ, nhưng trong một nghĩa hẹp, phương pháp "chọn" là những gì tôi đã được sau khi trong câu hỏi này. Cảm ơn rất nhiều. – allanberry

+0

Có, 'grep' là tuyệt vời, một phần vì nó sử dụng' === 'để so sánh các phần tử của người nhận với đối số' grep'. Điều đó cho phép bạn viết, ví dụ, '[" abc "," bcd "," cbd "]. Grep (/. B. /) # => [" Abc "," cbd "]' và '[{a : 1}, 4, {b: 2}, "mũ"]. Grep (băm) # => [{: a => 1}, {: b => 2}] '. –

3

Chúng tôi có thể truy cập mà không cần regex cho vấn đề cụ thể này. Sử dụng 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