【问题标题】:How do I create nested FOR loops with varying depths, for a varying number of arrays?如何为不同数量的数组创建具有不同深度的嵌套 FOR 循环?
【发布时间】:2012-01-23 02:47:36
【问题描述】:

我在一个巨大的数组中有不同数量的数组。这是正确的方法吗?:

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

如何为每个连续数组创建一系列嵌套循环,从而在前一个数组中创建数组循环?

parentArray.each do |eacharray|

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

     ...
    ...
   end    
  end
 end
end

例子:

网络蜘蛛将访问包含链接的第一页,并将其存储为数组。蜘蛛访问第一页上的第一个链接,并在该级别发现更多链接,并将其存储为数组。蜘蛛不断前进,不断发现越来越多的链接,直到深入到最深的层次。

我最终得到:

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

执行.flatten 会破坏所有深度关系。

我需要的是一个递归(树?)例程,它将从第一个数组(AKA arrayLinks)开始执行递归嵌套循环,并在第一个数组中构建另一个循环,依此类推。

@Justice,基本上我有很多数组。第一个数组是“父”,然后下一个数组是“父”的每个值的子。如果有另一个数组,那么它将是前一个数组的每个值的子元素。

【问题讨论】:

  • 一般来说,你想做什么?你为什么要创建和循环嵌套数组?
  • 你想对每个级别做不同的事情还是对所有级别都做同样的事情?
  • JRL,每个级别都做同样的事情。比如输出数组值。
  • @Justice,基本上我有很多数组。第一个数组是“父”,然后下一个数组是“父”的每个值的子。如果有另一个数组,那么它将是前一个数组的每个值的子元素。
  • 有一个解释的例子会有所帮助,显示每个数组的内容以及它们如何相互关联。听起来你对一棵树有某种奇怪的表示,但就你到目前为止所描述的而言,它听起来并不可行。假设它确实对你有用,一些实际的细节可能会阐明如何......

标签: ruby


【解决方案1】:

如果您只关心对所有级别运行相同的指令,那么您可以简单地 flatten 数组(使其成为一维)然后运行您的指令:

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

这会将所有维度递归地展平为一个维度。我相信这仅适用于 Ruby 1.9 及更高版本。

【讨论】:

  • 诺诺。一维不是我的目标。请阅读我发送给@Justice 的信息。
  • @gweg:它不会修改您的多维数组(因为您必须使用 flatten!),它会创建一个副本,允许您在每个元素上运行指令而无需嵌套任何语句。
  • 这将简单地遍历所有数组。这不是我想要的。
  • flatten 在 Ruby 1.8 中也可用。
【解决方案2】:

我已经使用递归解决了类似的问题。

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

您使用processArrays([], topArray) 调用它,每个级别都将包含父数组(到目前为止)和剩余数组的数组。

【讨论】:

    【解决方案3】:
        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)
    

    这个输出:

    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
    

    【讨论】:

      【解决方案4】:

      问题:为 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
      

      结果:

      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 
      

      【讨论】:

        【解决方案5】:

        我创建了一个脚本,它假定内部循环被重写为称为innerloop(arrayOfCurrentValues) 的方法。该方法被调用的次数与要运行的组合一样多,每次传递的数组都包含每个嵌套循环中当前选择的值,按照从最外层循环到最内层循环的顺序。

        数组a 是你的parentArray

        这是代码和演示:

        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
        

        【讨论】:

        • 每次调用 traverse() 时调用 params.size 效率低下 - 您当然可以将此代码包装在一个类中,该类的参数大小只计算一次并保存在一个字段中。您甚至可以将对 innerLoop(a) 的调用重构为传递给对象的块...
        【解决方案6】:
        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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-10
          • 2019-11-12
          • 2011-11-03
          • 1970-01-01
          • 2014-11-24
          相关资源
          最近更新 更多