allanberry
allanberry

Reputation: 7785

Ruby: filter array by regex?

This is a common, repetitive idiom for me: filtering an array using a regular expression, and returning a sub-array. My approach doesn't seem very Ruby-like (I come from Java). I end up having many methods which look a lot like this.

What is the idiomatic Ruby way to improve this code?

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

Upvotes: 42

Views: 54994

Answers (6)

Timo Schilling
Timo Schilling

Reputation: 3073

images = %w[foo.gif foo.png foo.jpg bar.jpeg moo.JPG]
images.grep(/.jpg/i) # => ["foo.jpg", "moo.JPG"]

Upvotes: 14

gucio
gucio

Reputation: 11

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

Upvotes: 1

Arup Rakshit
Arup Rakshit

Reputation: 118299

We can go without regex for this specific problem. Use 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"]

Upvotes: 5

steenslag
steenslag

Reputation: 80105

Have a look at Enumerable.grep, it's a very powerful way of finding/filtering things in anything enumerable.

Upvotes: 25

the Tin Man
the Tin Man

Reputation: 160631

If you want to find all gifs:

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

If you want to find all jpegs:

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

Running them:

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

But wait! There's more!

What if you want to group them all by their type, then extract based on the extension?:

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

Here's the types of files:

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

Here's how to grab specific types:

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

Upvotes: 79

Philip Hallstrom
Philip Hallstrom

Reputation: 19899

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

The change to your regexp is so that you can match "jpeg" in addition to "jpg" regardless of case.

Upvotes: 16

Related Questions