Reputation: 1214
I've got an array of strings. A few of the strings in this array contain a certain substring I'm looking for. I want to get an array of those strings containing the substring.
I would hope to do it like this:
a = ["abc", "def", "ghi"]
o.select(&:include?("c"))
But that gives me this error:
(repl):2: syntax error, unexpected ')', expecting end-of-input
o.select(&:include?("c"))
^
Upvotes: 0
Views: 3516
Reputation: 9485
You can use the &
-shorthand here. It's rather irrational (don't do this), but possible.
If you do manage to find an object and a method so you can make checks in your select
like so:
o.select { |e| some_object.some_method(e) }
(the important part is that some_object
and some_method
need to be the same in all iterations)
...then you can use Object#method
to get a block like that. It returns something that implements to_proc
(a requirement for &
-shorthand) and that proc, when called, calls some_method
on some_object
, forwarding its arguments to it. Kinda like:
o.m(a, b, c) # <=> o.method(:m).to_proc.call(a, b, c)
Here's how you use this with the &
-shorthand:
collection.select(&some_object.method(:some_method))
In this particular case, /c/
and its method =~
do the job:
["abc", "def", "ghi"].select(&/c/.method(:=~))
Kinda verbose, readability is relatively bad.
Once again, don't do this here. But the trick can be helpful in other situations, particularly where the proc is passed in from the outside.
Note: you may have heard of this shorthand syntax in a pre-release of Ruby 2.7, which was, unfortunately, reverted and didn't make it to 2.7:
["abc", "def", "ghi"].select(&/c/.:=~)
Upvotes: 5
Reputation: 114188
If your array was a file lines.txt
abc
def
ghi
Then you would select the lines containing c
with the grep
command-line utility:
$ grep c lines.txt
abc
Ruby has adopted this as Enumerable#grep
. You can pass a regular expression as the pattern and it returns the strings matching this pattern:
['abc', 'def', 'ghi'].grep(/c/)
#=> ["abc"]
More specifically, the result array contains all elements for which pattern === element
is true:
/c/ === 'abc' #=> true
/c/ === 'def' #=> false
/c/ === 'ghi' #=> false
Upvotes: 5
Reputation: 2747
You are almost there, you cannot pass parameter in &:
. You can do something like:
o.select{ |e| e.include? 'c' }
Upvotes: 2