For an array a, I would like to know all the indices i where a[i]
fulfils
some condition. My solution (which works) looks like this:
a=%w(Deutschlandsberg Stainz Preding Eibiswald)
(0…a.size).select {|i| a[i]=~/g$/} # ==> [0,2]
What I don’t like with this solution is that inside the code block
supplied to select, I also have to access the array variable a which
is declared outside. I would prefer having my code block “self
contained”, using only the variables passed as parameter.
Is there in Ruby a function similar select, where I also get the array
element passed through, kind of:
a.select_index {|index,value| value?~/g$/}
or do I have to write my own here? I don’t want to reinvent the
wheel…
Ronald
Alle giovedì 23 agosto 2007, Ronald F. ha scritto:
contained", using only the variables passed as parameter.
Is there in Ruby a function similar select, where I also get the array
element passed through, kind of:
a.select_index {|index,value| value?~/g$/}
or do I have to write my own here? I don’t want to reinvent the
wheel…
Ronald
You can do this:
require ‘enumerator’
a.enum_for(:each_with_index).select{|value, index value.match /g$/
}.map{|value, index| index}
enum_for returns an object of class Enumerable::Enumerator whose each
method
calls the argument of enum_for, in this case each_with_index. select
then
returns an array of pairs [value, index], where value are matching
values and
index their index in a. To extract only the indices, map is called on
this
array. The downside of this approach is that it needs two iterations:
one on
the original array and one on the array of matching results. If this is
a
problem, you can use this:
a.enum_for(:each_with_index).inject([]){|res, i|
i[0].match( /g$/) ? res << i[1] : res
}
or
matching = []
a.enum_for(:each_with_index).each{|value, index|
matching << index if value.match(/g$/)
}
I hope this helps
Stefano
If this is a
problem, you can use this:
a.enum_for(:each_with_index).inject([]){|res, i|
i[0].match( /g$/) ? res << i[1] : res
}
This is an idea I like! Thanks a lot!
Ronald
Posted by Ronald F. (Guest) on 23.08.2007 12:59
…
Is there in Ruby a function similar select, where I also get the array element passed through, kind of:
a.select_index {|index,value| value?~/g$/}
or do I have to write my own here? I don’t want to reinvent the wheel…
Ronald
How about:
module Enumerable
def select_index
index = -1
(block_given? && self.class == Range || self.class == Array) ?
collect { |x| index += 1; yield(x,index) }.compact : self
end
end
p (“a”…“n”).select_index { |x,i| i if x =~ /[c-g]/ }
=> [2, 3, 4, 5, 6]
Cheers,
j.k.
On Aug 23, 8:08 am, “Ronald F.” [email protected]
wrote:
–
Ronald F. [email protected]
Phone: +49-89-452133-162
accum = []
a.each_with_index{|s,i| accum << i if s =~ /g$/ }
2007/8/23, Ronald F. [email protected]:
a.enum_for(:each_with_index).inject([]){|res, i|
i[0].match( /g$/) ? res << i[1] : res
}
This is an idea I like! Thanks a lot!
And you can make it even easier to read:
a.enum_for(:each_with_index).inject([]){|res, (elem, idx)|
elem.match( /g$/) ? res << idx : res
}
Regards,
Pit
William J. [email protected] wrote:
Ronald
Ronald F. [email protected]
Phone: +49-89-452133-162
accum = []
a.each_with_index{|s,i| accum << i if s =~ /g$/ }
And to generalize further, let’s abstract the test (it shouldn’t matter
what the test is, just as it shouldn’t matter what the array is):
#specific part
a=%w(Deutschlandsberg Stainz Preding Eibiswald)
test = Proc.new {|s| s=~/g$/}
#general part
result = []
a.each_with_index {|ss,ix| result << ix if test.call(ss)}
Or, even more general (because the names stop mattering):
def indices_matching_test(a)
result = []
a.each_with_index {|ss,ix| result << ix if yield ss}
result
end
#and here’s how to use it:
a=%w(Deutschlandsberg Stainz Preding Eibiswald)
test = Proc.new {|s| s=~/g$/}
puts indices_matching_test(a, &test)
m.
On Aug 24, 1:44 pm, [email protected] (matt neuburg) wrote:
This is an idea I like! Thanks a lot!
what the test is, just as it shouldn’t matter what the array is):
#specific part
a=%w(Deutschlandsberg Stainz Preding Eibiswald)
test = Proc.new {|s| s=~/g$/}
Why so prolix?
test = proc{|s| s =~ /g$/}
result
end
#and here’s how to use it:
a=%w(Deutschlandsberg Stainz Preding Eibiswald)
test = Proc.new {|s| s=~/g$/}
puts indices_matching_test(a, &test)
Even better:
p indices_matching_test(a){|s| s =~ /g$/}