在ruby中创建任意深度的嵌套循环

时间:2012-08-06 04:07:54

标签: ruby

我想写一个ruby程序,它以任意数量的维度跨越空间。

我正在做的3个方面看起来像这样:

x_range = (-1..1)
y_range = (-1..1)
z_range = (-1..1)

step_size = 0.01

x_range.step(step_size) do |x|
  y_range.step(step_size) do |y|
    z_range.step(step_size) do |z|

      # do something with the point x,y,z

    end  
  end
end

我想对n尺寸

做同样的事情

5 个答案:

答案 0 :(得分:2)

这是我想到的第一件事:

def enumerate(nDimens, bottom, top, step_size)
  bottom = (bottom / step_size).to_i
  top    = (top    / step_size).to_i

  range = (bottom..top).to_a.map{ |x| x * step_size }
  return range.repeated_permutation(nDimens)
end

stepper = enumerate(4, -1, 1, 0.1)

loop do
  puts "#{stepper.next()}"
end

这会产生:

[-1.0, -1.0, -1.0, -1.0]
[-1.0, -1.0, -1.0, -0.9]
[-1.0, -1.0, -1.0, -0.8]
# Lots more...
[1.0, 1.0, 1.0, 0.8]
[1.0, 1.0, 1.0, 0.9]
[1.0, 1.0, 1.0, 1.0]

这假设所有尺寸都具有相同的范围,但如果由于某种原因不能保持,则很容易调整。

答案 1 :(得分:1)

递归可以轻松而完美地解决这类问题。以下代码适合任意数量的维度,以及不同长度的范围

def traversal(ranges, step_size, conjunction = [], &blk)
  ranges[0].step(step_size) do |x|
    conjunction.push(x)
    if ranges.size > 1
      traversal(ranges[1..-1], step_size, conjunction, &blk)
    else
      blk.call(conjunction) if block_given?
      conjunction.pop
    end
  end
  conjunction.pop
end

运行:(dimension = 4,length = 3,3,4,2)

x = (1..3)
y = (4..6)
z = (7..10)
w = (100..101)
test_data = [x, y, z, w]
step_size = 1

traversal(test_data, step_size) do |x|
  puts "Point: #{x.join('-')}"
end

输出:(总共72分,即3 * 3 * 4 * 2)

Point: 1-4-7-100
Point: 1-4-7-101
Point: 1-4-8-100
Point: 1-4-8-101
Point: 1-4-9-100
Point: 1-4-9-101
Point: 1-4-10-100
Point: 1-4-10-101
Point: 1-5-7-100
Point: 1-5-7-101
Point: 1-5-8-100
Point: 1-5-8-101
Point: 1-5-9-100
Point: 1-5-9-101
Point: 1-5-10-100
Point: 1-5-10-101
Point: 1-6-7-100
Point: 1-6-7-101
Point: 1-6-8-100
Point: 1-6-8-101
Point: 1-6-9-100
Point: 1-6-9-101
Point: 1-6-10-100
Point: 1-6-10-101
Point: 2-4-7-100
Point: 2-4-7-101
Point: 2-4-8-100
Point: 2-4-8-101
Point: 2-4-9-100
Point: 2-4-9-101
Point: 2-4-10-100
Point: 2-4-10-101
Point: 2-5-7-100
Point: 2-5-7-101
Point: 2-5-8-100
Point: 2-5-8-101
Point: 2-5-9-100
Point: 2-5-9-101
Point: 2-5-10-100
Point: 2-5-10-101
Point: 2-6-7-100
Point: 2-6-7-101
Point: 2-6-8-100
Point: 2-6-8-101
Point: 2-6-9-100
Point: 2-6-9-101
Point: 2-6-10-100
Point: 2-6-10-101
Point: 3-4-7-100
Point: 3-4-7-101
Point: 3-4-8-100
Point: 3-4-8-101
Point: 3-4-9-100
Point: 3-4-9-101
Point: 3-4-10-100
Point: 3-4-10-101
Point: 3-5-7-100
Point: 3-5-7-101
Point: 3-5-8-100
Point: 3-5-8-101
Point: 3-5-9-100
Point: 3-5-9-101
Point: 3-5-10-100
Point: 3-5-10-101
Point: 3-6-7-100
Point: 3-6-7-101
Point: 3-6-8-100
Point: 3-6-8-101
Point: 3-6-9-100
Point: 3-6-9-101
Point: 3-6-10-100
Point: 3-6-10-101

答案 2 :(得分:0)

如果范围不是太大,你可以这样做:

n = 5 # 5 dimentions
x = (-1..1).to_a
x.product(*[x]*(n-1)).each {|i| p i}

结果:

[-1, -1, -1, -1, -1]
[-1, -1, -1, -1, 0]
[-1, -1, -1, -1, 1]
[-1, -1, -1, 0, -1]
[-1, -1, -1, 0, 0]
[-1, -1, -1, 0, 1]
[-1, -1, -1, 1, -1]
[-1, -1, -1, 1, 0]
[-1, -1, -1, 1, 1]
[-1, -1, 0, -1, -1]
[-1, -1, 0, -1, 0]
# skipped

答案 3 :(得分:0)

这是你可以做的......这是一个示例迭代器。

#next(l[dim] array of lower ranges ,h[dim] = upper ranges, step[dim], dim = dimensions -1, curr[dim] = current state in dim dimensions )
def nextx(l ,h, step, dim, curr)
    x = dim
    update= false
    while (update==false)
        if curr[x] == h[x]
            if x > 0
                x = x-1
            else
                exit
            end

        else
            curr[x]= curr[x]+step[x]
            while (x < dim)
                x = x+1
                curr[x] = l[x]  
            end
            update = true
        end
    end
    return curr
end


l = [0,0,0]
h = [3,3,3]
step = [1,1,1]
currx = [0,0,2]

i = 0
while i < 70
    currx = nextx(l, h, step, 2, currx)
    puts currx.inspect
    i=i+1
end

答案 4 :(得分:0)

在探索搜索空间的算法中通常会遇到这种情况。 do循环从一维范围创建乘积空间。

首先需要将尽可能多的范围打包到一个数组中,例如

search_space_1Ds = [x_range.step(step_size).to_a, y_range.step(step_size).to_a, z_range.step(step_size).to_a]

那么以下内容将适用于任意数量的尺寸。

search_space = search_spaces_1Ds.shift.product(*search_space_1Ds)
search_space.map do |vec|
  # calculate something with vec
end

此实现不仅简洁明了,还使您的算法非常清楚;通过搜索空间进行枚举,该空间是一维搜索空间的乘积空间。