开发者

How do I create nested FOR loops with varying depths, for a varying number of arrays?

开发者 https://www.devze.com 2022-12-11 07:06 出处:网络
I have varying number of arrays within one giant array. Is this the right approach?: parentArray = [[array],[array2],....]

I have varying number of arrays within one giant array. Is this the right approach?:

parentArray = [[array],[array2],....]

How can I create a series of nested loops for each consecutive array, so creating array loops within the previous one?

parentArray.each开发者_运维技巧 do |eacharray|

    array.each do |eacharray1|
     array2.each do |eacharray2|
      array3.each do |eacharray3|
       arrayN.each do ....
         .....
          .....

     ...
    ...
   end    
  end
 end
end

Example:

A web-spider will visit the first page containing links, and store this as array. The spider visits the first link on the first page, and discovers a lot more links at this level, and stores this as array. The spider keeps going and keeps discovering more and more links until it goes to the deepest level.

I end up with:

rootArray = [arrayLinks, arrayLink2, arrayLinks3....]

Doing .flatten will destroy all depth relationships.

What I need is a recursive (tree?) routine that will do a recursive nested loop starting with the very first array, AKA arrayLinks, and building another loop inside the first, and so on.

@Justice, basically I have many arrays. the first array is the "parent", then the next array is the children of each value's of "parent". If there is another array, then it will be the children of each value of immediate previous array.


If all you care about is to run the same instruction for all levels, then you can simply flatten the array (makes it one dimensional) and then run your instruction:

parentArray.flatten.each do |element|
   puts element
end

This will recursively flatten all dimensions to a single dimension. I believe this is only available in Ruby 1.9 and above.


I've solved similar problems using recursion.

def processArrays(parents, arrs)
  if not arrs.empty?
    a0 = arrs[0]
    parents.push(a0)
    a0.each {|a0x| processArrays(parents, arrs[1..-1])
    parents.pop
  end
end

You call it with processArrays([], topArray) and each level will have the array of parents (so far) and an array of remaining arrays to work with.


    parentArray = [[1,2],[3,4,['alpha','beta']],'a','b','c']

def processArray(array,depth)
  array.each do |element|
       if element.is_a?(Array)
          processArray(element,depth+1)
       else
          puts "Element at Depth #{depth.to_s} is #{element.to_s}"
       end
  end
end


processArray(parentArray,1)

this outputs:

Element at Depth 2 is 1
Element at Depth 2 is 2
Element at Depth 2 is 3
Element at Depth 2 is 4
Element at Depth 3 is alpha
Element at Depth 3 is beta
Element at Depth 1 is a
Element at Depth 1 is b
Element at Depth 1 is c


problem: create nested loops for each array in parentArray = [[array1],[array2],....]

a = [[1,2,3],[:a,:b],[:X,:Z]]
a.first.product(*a.drop(1)).each do |i|
  i.size.times {|p| printf("i[%d]=%s ",p,i[p])}
  puts
end

result:

i[0]=1 i[1]=a i[2]=X
i[0]=1 i[1]=a i[2]=Z 
i[0]=1 i[1]=b i[2]=X
i[0]=1 i[1]=b i[2]=Z 
i[0]=2 i[1]=a i[2]=X 
i[0]=2 i[1]=a i[2]=Z 
i[0]=2 i[1]=b i[2]=X 
i[0]=2 i[1]=b i[2]=Z 
i[0]=3 i[1]=a i[2]=X 
i[0]=3 i[1]=a i[2]=Z 
i[0]=3 i[1]=b i[2]=X 
i[0]=3 i[1]=b i[2]=Z 


I've created a script that assumes that the inner loop is rewritten as a method called innerloop(arrayOfCurrentValues). The method gets called as many times as there are combinations to be run, each time the array passed contains the currently selected value from each nested loop, in order from outermost loop to innermost loop.

The array a here is your parentArray.

Here's the code and a demo:

Script started on Sat Nov  7 21:55:40 2009
bash-3.2$ cat loops.rb
a = [[1,2,3],[:a,:b],[51,52,53,54]]

def innerloop(arrayOfCurrentValues)
  puts "innerloop("+arrayOfCurrentValues.inspect+")"
end

def traverse(accumulated,params, index) 
 if (index==params.size)
  return innerloop(accumulated) 
 end

 currentParam = params[index]
 currentParam.each do |currentElementOfCurrentParam|
  traverse(accumulated+[currentElementOfCurrentParam],params, index+1)
 end

end


traverse([],a,0)



bash-3.2$ ruby loops.rb
innerloop([1, :a, 51])
innerloop([1, :a, 52])
innerloop([1, :a, 53])
innerloop([1, :a, 54])
innerloop([1, :b, 51])
innerloop([1, :b, 52])
innerloop([1, :b, 53])
innerloop([1, :b, 54])
innerloop([2, :a, 51])
innerloop([2, :a, 52])
innerloop([2, :a, 53])
innerloop([2, :a, 54])
innerloop([2, :b, 51])
innerloop([2, :b, 52])
innerloop([2, :b, 53])
innerloop([2, :b, 54])
innerloop([3, :a, 51])
innerloop([3, :a, 52])
innerloop([3, :a, 53])
innerloop([3, :a, 54])
innerloop([3, :b, 51])
innerloop([3, :b, 52])
innerloop([3, :b, 53])
innerloop([3, :b, 54])
bash-3.2$ exit
exit

Script done on Sat Nov  7 21:55:51 2009


module Scratch
  def self.recur(arr, depth, &fn)
    arr.each do |a| 
      a.is_a?(Array) ?  recur(a, depth+1, &fn) : fn.call(a, depth)
    end
  end
  arr = [[1, 2, 3], 4, 5, [6, 7, [8, 9]]]
  recur(arr, 0) { |x,d| puts "#{d}: #{x}" }
end
0

精彩评论

暂无评论...
验证码 换一张
取 消