【问题标题】:Retrieving largest indices of the bounded element in a multidimensional array in Scala在Scala中检索多维数组中有界元素的最大索引
【发布时间】:2012-01-15 08:23:12
【问题描述】:

我有一个多维数组:

val M = Array.ofDim[Int](V, N)

目标是找到存在有界元素 0

目前我有这段代码 sn-p 可以工作,但想知道是否有更好、更有效的方法来做到这一点。

M.zipWithIndex.reverse.collectFirst({
  case (arr, ind) if arr.exists(a => a <= W && a > 0) => {
    arr.zipWithIndex.find(a => a._1 <= W && a._1 > 0) match {
      case Some((weight, ind2)) => (ind, ind2, weight)
    }
  }
})

【问题讨论】:

    标签: arrays scala indexing indices


    【解决方案1】:

    嗯,和其他的很像,但是找到目标就停止了

    def find(M: Array[Array[Int]], W: Int): Option[(Int, Int, Int)] = {
      for {
        x <- M.indices.reverse
        y <- M(x).indices
        a = M(x)(y)
        if 0 < a && a <= W
      } return Some(x, y, a)
      None
    }
    

    【讨论】:

      【解决方案2】:

      在这里使用命令式或递归解决方案真的会更好。我会写一个递归的:

      def finder(arr: Array[Array[Int]], w: Int, i: Int = 0, j: Int = 0): Option[(Int,Int,Int)] = {
        val ri = arr.length-i-1
        if (i >= arr.length) None
        else if (arr(ri)(j) > 0 && arr(ri)(j) < w) Some(ri,j,arr(ri)(j))
        else if (j+1 < arr(i).length) finder(arr,w,i,j+1)
        else finder(arr,w,i+1)
      }
      

      然后finder(M,W) 应该做你想做的事。请注意,这也是有效的——除了返回值之外没有装箱。


      编辑——如果您关心性能,这里是现有解决方案在 100x100 阵列上的运行时间,该阵列没有解决方案或一个解决方案在 77% 的最后(即运行时间应该是大约 1/4) :

      Original without answer:     65 μs / iteration
      Original with answer at 1/4: 18 μs / iteration
      

      结果表与原始方法相比,所花费的相对时间(越低越快,使用 -optimise 编译但几乎没有区别):

                        No Answer    1/4 Answer
      Original            1.00          1.00
      Rex                 0.55          0.72
      4e6                 1.95          7.00
      missingfaktor       2.41          1.91
      Luigi               4.93          3.92
      

      所以你原来的方法实际上比所有的建议都快,除了递归的。

      【讨论】:

      • 这就是为什么我们需要快速的for 循环。 :(
      • 奇怪的是,当没有答案时,我的速度如此之慢,因为它或多或少与 4e6 相同
      • @LuigiPlinge - 这也让我感到惊讶,但看起来确实是一致的。
      【解决方案3】:

      正如@Rex 所说,这种情况下的命令式方法看起来更简单

      scala> val m = Array.tabulate(v,n)(_ + _)
      m: Array[Array[Int]] = Array(Array(0, 1, 2, 3), Array(1, 2, 3, 4), Array(2, 3, 4, 5))
      
      scala> for { 
           | i <- v-1 to 0 by -1
           | j <- n-1 to 0 by -1
           | if m(i)(j) > 0 && m(i)(j) < 2
           | } yield (i, j, m(i)(j))
      res23: scala.collection.immutable.IndexedSeq[(Int, Int, Int)] = Vector((1,0,1), (0,1,1))
      
      scala> res23.headOption
      res24: Option[(Int, Int, Int)] = Some((1,0,1))
      

      【讨论】:

        【解决方案4】:

        我会写一个迭代器。

        scala> def itr[A](as: Array[Array[A]]) = new Iterator[(Int, Int, A)] {
             |   private var r = 0 
             |   private var c = -1
             |   def next = {
             |     if(c == as(r).length - 1) {
             |       c = 0
             |       r += 1
             |     } else {
             |       c += 1
             |     }
             |     (r, c, as(r)(c))
             |   }
             |   def hasNext = {
             |     !((r == as.length - 1) && (c == as(r).length - 1))
             |   }
             | }
        itr: [A](as: Array[Array[A]])java.lang.Object with Iterator[(Int, Int, A)]
        
        scala> val xs = Array.tabulate(5, 6)(_ + _)
        xs: Array[Array[Int]] = Array(Array(0, 1, 2, 3, 4, 5), Array(1, 2, 3, 4, 5, 6), Array(2, 3, 4, 5, 6, 7), Array(3, 4, 5, 6, 7, 8), Array(4, 5, 6, 7, 8, 9))
        
        scala> itr(xs).find { case (_, _, x) => 5 < x && x <= 7 }
        res19: Option[(Int, Int, Int)] = Some((1,5,6))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-20
          • 1970-01-01
          相关资源
          最近更新 更多