Scala列表的上三角循环习语

时间:2013-09-09 21:13:28

标签: scala nested-loops functor

从命令式编程的背景来看,我习惯于做

for (i = 0;  i < 1000000;  i++) {
    for (j = i + 1;  j < 1000000;  j++) {
        doSomething(array[i], array[j])
    }
}

检查百万元素数组中的所有唯一对。 doSomething是一些在对角线上对角线和对称或反对称结果产生琐碎结果的操作 - 这就是为什么我只想在上三角形上工作。 (这里有一个很小的变体,i == j案例很有意思;这很容易解决。)

我发现自己奇怪地试图在Scala中这样做。我有一个很大的List,想要对所有成对组合做一些事情,但是

list.flatMap(x => list.map(y => doSomething(x, y))

包括所有冗余或微不足道的案例(两个太多的工作因素)和

(0 until 1000000).flatMap({i =>
  (0 until 1000000).map({j =>
    doSomething(list(i), list(j))
  })
})

会非常错误,因为列表不是随机访问(N ^ 2因子太多)。我可以将Lists转换为Arrays,但这感觉就像错过了重点。 Lists是链接列表,因此我的命令示例中的j + 1元素距离我目前正在检查的i只有一步之遥。我确信我可以用C / Python /中的链接列表编写一个有效的上三角循环。

我想我现在可以吞下两个因子,但这是一个常见的情况,因为感觉应该有一个很好的解决方案。

此外,这个“上三角形环”是否有一个共同的名称?我找不到一个好的搜索字符串。

编辑:以下是一个糟糕解决方案的示例:

list.zipWithIndex.flatMap({case (x, i) =>
  list.zipWithIndex.map({case (y, j) =>
    if (j > i)
      doSomething(x, y)
    else
      Nil
  })
})

因为它仍会访问不需要的节点。

3 个答案:

答案 0 :(得分:6)

您可能希望查看Vector数据类型,它允许基于快速索引的查找。

此外,还有一种内置的组合方法,可以为您提供所需的内容。

scala> (1 to 3).combinations(2).mkString(" ")
res1: String = Vector(1, 2) Vector(1, 3) Vector(2, 3)

答案 1 :(得分:5)

您可以通过以下方式使用模式匹配和尾递归:

@tailrec def walk[T](list: Seq[T]): Unit =
  list match {
    case head :: tail =>
      tail.foreach(doSomething(head, _))
      walk(tail)
    case Nil =>
  }

答案 2 :(得分:-1)

关于这部分问题:

  

此外,这是&#34;上三角形循环&#34;有一个共同的名字?我无法为它找到一个好的搜索字符串。

&#34;上三角形循环&#34;的通用名称是三角矩阵。 (如wikipedia

中所述
  

...三角矩阵是一种特殊的方阵。如果主对角线上方的所有条目都为零,则方阵称为下三角形。类似地,如果主对角线下方的所有条目都为零,则方形矩阵称为上三角形。