I’m trying to do something regarding looping through an array, but only
with elements I need. I’m not sure exactly how to go about it to make it
the most efficient. Is there basically a way to do something like:
for row in @large_row_array WHERE row.element == “something”
… some some stuff
end
What would be the best way to accomplish the above? Would I use perhaps
some nested loops? Thanks for any help, I’m just getting started with
Ruby along with more indepth programming in general and I’m loving it.
You can use Array#select to get the values you want:
for row in @large_row_array.select{ |row| row.element == “something” }
something
end
Marston A. wrote:
Ruby along with more indepth programming in general and I’m loving it.
I’m not sure if it’s always more efficient, but you can use grep in some
cases:
irb(main):003:0> ENV.keys.grep(/ruby/i) {|key| p key}
“RUBYOPT”
“RUBYLIB”
This is more or less the same as
irb(main):004:0> ENV.keys.each {|key| if /ruby/i === key then p key end}
“RUBYOPT”
“RUBYLIB”
(The return values are quite different though.)
So as long as you are working with tests that can be expressed using
#===, you can use #grep. It’s compact, and at least sometimes more
efficient.
require ‘benchmark’
a = (0…1_000_000).map {|i| i.to_s}
def foo s
end
Benchmark.bmbm do |b|
b.report(“grep”) do
a.grep(/^10*$/) {|s| foo s}
end
b.report(“each-if”) do
a.each {|s| if /^10*$/ === s then foo s end }
end
b.report(“select-each”) do
a.select {|s| /^10*$/ === s}.each {|s| foo s}
end
end
END
Rehearsal -----------------------------------------------
grep 0.490000 0.000000 0.490000 ( 0.492667)
each-if 0.640000 0.000000 0.640000 ( 0.638102)
select-each 0.760000 0.000000 0.760000 ( 0.758676)
-------------------------------------- total: 1.890000sec
user system total real
grep 0.490000 0.000000 0.490000 ( 0.487539)
each-if 0.640000 0.000000 0.640000 ( 0.639301)
select-each 0.620000 0.010000 0.630000 ( 0.621152)
Marston A. wrote:
for row in @large_row_array WHERE row.element == “something”
… some some stuff
end
@array.select{|row| row.element == “something”}.each do |row|
… some stuff
end
Cheers,
Daniel
Joel VanderWerf wrote:
Marston A. wrote:
…
for row in @large_row_array WHERE row.element == “something”
… some some stuff
end
…
So as long as you are working with tests that can be expressed using
#===, you can use #grep.
In your case, grep may not be so useful after all. You would have to
define an object whose #=== method performs the row.element ==
“something” test.
require ‘benchmark’
tester = Object.new
def tester.===(row)
row.element == 987654
end
class Row
attr_accessor :element
end
rows = (0…1_000_000).map {|i| r = Row.new; r.element = i; r}
Benchmark.bmbm do |b|
b.report(“grep”) do
rows.grep(tester) {|row|}
end
b.report(“each-if”) do
rows.each {|row| if row.element == 987654 then nil end }
end
b.report(“select-each”) do
rows.select {|row| row.element == 987654}.each {|row|}
end
end
END
Rehearsal -----------------------------------------------
grep 0.720000 0.000000 0.720000 ( 0.725553)
each-if 0.590000 0.000000 0.590000 ( 0.587160)
select-each 0.770000 0.000000 0.770000 ( 0.768704)
-------------------------------------- total: 2.080000sec
user system total real
grep 0.730000 0.000000 0.730000 ( 0.735809)
each-if 0.590000 0.000000 0.590000 ( 0.587350)
select-each 0.570000 0.000000 0.570000 ( 0.564276)
Thanks everyone, I this was exactly what I needed.
Marston A. wrote:
I’m trying to do something regarding looping through an array, but only
with elements I need. I’m not sure exactly how to go about it to make it
the most efficient. Is there basically a way to do something like:
for row in @large_row_array WHERE row.element == “something”
… some some stuff
end
You can use array.select as the others have mentioned, or you can use
next like this:
for row in @large_row_array
next unless row.element == “something”
… some some stuff
end
That might be a bit quicker over large data sets, too – select will
loop through your data before the for loop.
Cheers,
Dave