foo[1..3].each do |i|
foo[i.x]
end
foo[1..3].each do |i| # iterates 3 arrays
# i is an array
i.each do |j| # iterates thousands of nodes for each array
#j is a node
node = foo[j.y][j.x]
end
end
#foo[1..3][1..3]
foo[1..3].each do |i| # iterates 3 arrays
# i is an array
i[1..3].each do |j|
#node = j
# or
node = foo[j.y][j.x]
end
end
VALUE
rb_ary_each(ary)
VALUE ary;
{
long i;
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(RARRAY(ary)->ptr[i]);
}
return ary;
}
VALUE
rb_ary_aref(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
VALUE arg;
long beg, len;
if (argc == 2) {
if (SYMBOL_P(argv[0])) {
rb_raise(rb_eTypeError, "Symbol as array index");
}
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
if (beg < 0) {
beg += RARRAY(ary)->len;
}
return rb_ary_subseq(ary, beg, len);
}
if (argc != 1) {
rb_scan_args(argc, argv, "11", 0, 0);
}
arg = argv[0];
/* special case - speeding up */
if (FIXNUM_P(arg)) {
return rb_ary_entry(ary, FIX2LONG(arg));
}
if (SYMBOL_P(arg)) {
rb_raise(rb_eTypeError, "Symbol as array index");
}
/* check if idx is Range */
switch (rb_range_beg_len(arg, &beg, &len, RARRAY(ary)->len, 0)) {
case Qfalse:
break;
case Qnil:
return Qnil;
default:
return rb_ary_subseq(ary, beg, len);
}
return rb_ary_entry(ary, NUM2LONG(arg));
}
require "benchmark"
class Room
attr_reader :x, :y
def initialize( x, y )
@x, @y = x, y
end
end
class ArrayBenchmark
def initialize( width, height, radius )
@foo = Array.new( height, Array.new( width ) )
@offset_x = width / 2
@offset_y = height / 2
@radius = radius
@foo.each_index do |y|
@foo[y].each_index do |x|
@foo[y][x] = Room.new( x, y )
end
end
end
def run( iter )
Benchmark.bmbm do |bm|
bm.report( "each" ) do
@foo[(@offset_y-@radius)..(@offset_y+@radius)].each do |i|
i[(@offset_x-@radius)..(@offset_x+@radius)].each do |j|
@foo[j.y][j.x]
end
end
end
bm.report( "for..in" ) do
for y in ((@offset_y-@radius)..(@offset_y+@radius))
for x in ((@offset_x-@radius)..(@offset_x+@radius))
@foo[y][x]
end
end
end
end
end
end
bm = ArrayBenchmark.new( 1_000, 1_000, 10 )
bm.run( 10_000 )
Rehearsal ——————————————-
each 0.000000 0.000000 0.000000 ( 0.000720)
for..in 0.000000 0.000000 0.000000 ( 0.000617)
———————————- total: 0.000000sec
user system total real
each 0.000000 0.000000 0.000000 ( 0.000698)
for..in 0.000000 0.000000 0.000000 ( 0.000601)
static VALUE
rb_obj_equal(obj1, obj2)
VALUE obj1, obj2;
{
if (obj1 == obj2) return Qtrue;
return Qfalse;
}
So the problem is you have no way of knowing the location of a given node without knowing the position in the array? In other words, that data is not saved on the individual location data?
Of course array[x][y] works to pluck them out…