Using grep on subarrays - help!

S

Simon Harrison

Can anyone help with this? I thought grep would find any element that
matches in an array. It seems not...


irb(main):028:0> test = [['one', 'vol1'], ['one', 'vol2'], ['two',
'vol3']]
=> [["one", "vol1"], ["one", "vol2"], ["two", "vol3"]]
irb(main):029:0> test.grep(/one/)
=> []
irb(main):030:0> test.each.grep(/one/)
=> []
irb(main):031:0> test
=> [["one", "vol1"], ["one", "vol2"], ["two", "vol3"]]
irb(main):032:0> test.grep('one')
=> []
irb(main):033:0> test2 = ['one', 'one', 'two', 'three']
=> ["one", "one", "two", "three"]
irb(main):034:0> test2.grep(/one/)
=> ["one", "one"]
irb(main):035:0>
 
J

Jesús Gabriel y Galán

Can anyone help with this? I thought grep would find any element that
matches in an array. It seems not...


irb(main):028:0> test = [['one', 'vol1'], ['one', 'vol2'], ['two',
'vol3']]
=> [["one", "vol1"], ["one", "vol2"], ["two", "vol3"]]
irb(main):029:0> test.grep(/one/)
=> []

test.each {|x| puts x.grep /one/}

=> one
one

If you want to choose all pairs that match:

result = []
test.each {|x| result << x unless x.grep(/one/).empty?}
result

=> [["one", "vol1"],["one","vol2"]]

Jesus.
 
S

Simon Harrison

Thanks again Jesus. Is it just me or does that seem a bit longwinded.
Any idea why one can't just directly an array with subarrays?
 
A

Adam Prescott

2011/4/3 Jes=C3=BAs Gabriel y Gal=C3=A1n said:
result =3D []
test.each {|x| result << x unless x.grep(/one/).empty?}
result

More to-the-point:

test.reject { |x| x.grep(/one/).empty? }
 
7

7stud --

Simon Harrison wrote in post #990675:
Can anyone help with this? I thought grep would find any element that
matches in an array. It seems not...

You are trying to use grep() to match strings, yet your test array does
not contain strings--it contains sub-arrays. So first you have to grab
the sub-arrays, and then you can apply grep to the sub-arrays because
they contain strings.
 
7

7stud --

7stud -- wrote in post #990727:
new_arr = test.select do |arr|
if arr.include?(target)
true
end
end

I guess that can be written more succinctly as:

new_arr = test.select do |arr|
arr.include?(target)
end
 
R

Robert Klemme

2011/4/3 Jes=FAs Gabriel y Gal=E1n said:
result =3D []
test.each {|x| result << x unless x.grep(/one/).empty?}
result

More to-the-point:

test.reject { |x| x.grep(/one/).empty? }

It seems we may want to match at the first position only, so I'd
rather do one of those

irb(main):003:0> test.select {|a,b| /one/ =3D~ a}
=3D> [["one", "vol1"], ["one", "vol2"]]
irb(main):004:0> test.select {|a,b| a =3D=3D "one"}
=3D> [["one", "vol1"], ["one", "vol2"]]

If we are only interested in the other bit

irb(main):005:0> test.select {|a,b| a =3D=3D "one"}.map {|a,b| b}
=3D> ["vol1", "vol2"]

Or, with #inject for a change since we know the key when doing exact matche=
s

irb(main):006:0> test.inject([]) {|r,(a,b)| a =3D=3D "one" ? r << b : r}
=3D> ["vol1", "vol2"]

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
S

Simon Harrison

Thanks for all the tips. I think #select fits best:

file_results = @films.select { |a, b| /#{@film}/i =~ a }


Just one question. Obviously in the above, a and b refer to the first
and second elements in each subarray. Let's say we have this array:

=> [["one", "two", "three"], ["one"], ["two", "three"], ["one",
"three"]]

What would be the best way to search for 'one' (or whatever) in this
case?

Cheers
 
R

Rob Biedenharn

Thanks for all the tips. I think #select fits best:

file_results = @films.select { |a, b| /#{@film}/i =~ a }


Just one question. Obviously in the above, a and b refer to the first
and second elements in each subarray. Let's say we have this array:

=> [["one", "two", "three"], ["one"], ["two", "three"], ["one",
"three"]]

What would be the best way to search for 'one' (or whatever) in this
case?

Cheers

irb> @films = [["one", "two", "three"], ["one"], ["two", "three"],
["one", "three"]]
=> [["one", "two", "three"], ["one"], ["two", "three"], ["one",
"three"]]
irb> @film = 'One'
=> "One"
irb> @films.select{|film,*_| /#{@film}/i =~ film}
=> [["one", "two", "three"], ["one"], ["one", "three"]]

_ is a valid identifier and I tend to use it to mean either "a
throwaway placeholder" (like in this usage) or "a quick, single block
arg" (as in arry.map{|_|_.something} to mean the same as
arry.map(&:something) without needing Symbol#to_proc).


-Rob

Rob Biedenharn
(e-mail address removed) http://AgileConsultingLLC.com/
(e-mail address removed) http://GaslightSoftware.com/
 
S

Simon Harrison

Thanks Rob,very useful. Any chance of expanding on this at all:

"a quick, single block
arg" (as in arry.map{|_|_.something} to mean the same as
arry.map(&:something) without needing Symbol#to_proc)."
 
R

Rob Biedenharn

Thanks Rob,very useful. Any chance of expanding on this at all:

"a quick, single block
arg" (as in arry.map{|_|_.something} to mean the same as
arry.map(&:something) without needing Symbol#to_proc)."



Here's a little example from an error handler in a script (first
occurrence in an open buffer):

rescue => e
if $stderr.isatty
$stderr.puts e.message
$stderr.puts e.backtrace.select {|_| %r{/app/} =~ _}.join("\n\t")
else
raise
end
end

While I could replace the "_" with a name like "line" or
"backtrace_line", that doesn't really increase the expressiveness when
the entire block is one statement/expression.

-Rob

Rob Biedenharn
(e-mail address removed) http://AgileConsultingLLC.com/
(e-mail address removed) http://GaslightSoftware.com/
 
7

7stud --

Simon Harrison wrote in post #990886:
Thanks for all the tips. I think #select fits best:

file_results = @films.select { |a, b| /#{@film}/i =~ a }


Just one question. Obviously in the above, a and b refer to the first
and second elements in each subarray. Let's say we have this array:

=> [["one", "two", "three"], ["one"], ["two", "three"], ["one",
"three"]]

Neither grep() or include?() depended on the size of the sub-arrays they
are searching, so the answer is the same:


data = [
["one", "two", "three"],
["one"],
["two", "three"],
["one","three"]
]

target = 'one'

results = data.select do |arr|
arr.include?(target)
end

p results

--output:--
[["one", "two", "three"], ["one"], ["one", "three"]]

However, if your target will only appear in the first position of the
array, then it is much more efficient to just check the first element of
each array:

data = [
["one", "two", "three"],
["ONE"],
["two", "three"],
["oNe","three"]
]

target = 'one'

results = data.select do |arr|
arr[0].downcase == target
end

p results

--output:--
[["one", "two", "three"], ["ONE"], ["oNe", "three"]]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top