在Scala中检索多维数组中有界元素的最大索引

时间:2011-12-07 20:09:27

标签: arrays scala indexing indices

我有一个多维数组:

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

目标是找到存在有界元素0<的最大V维度索引。 w0< = W并返回索引和元素值。

目前我有这个代码片段可以使用,但想知道是否有更好,更有效的方法来执行此操作。

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)
    }
  }
})

4 个答案:

答案 0 :(得分:5)

Meh,与其他人非常相似,但是当它找到目标时会停止

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
}

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

正如@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))

答案 3 :(得分:0)

我会写一个迭代器。

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))