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
精彩评论