从命令式编程的背景来看,我习惯于做
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
})
})
因为它仍会访问不需要的节点。
答案 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)
中所述...三角矩阵是一种特殊的方阵。如果主对角线上方的所有条目都为零,则方阵称为下三角形。类似地,如果主对角线下方的所有条目都为零,则方形矩阵称为上三角形。