scala中的double for循环,内部索引递增

时间:2016-09-10 17:29:42

标签: scala

我试图创建一个简单的函数来查找列表中最近的两个对。由于此操作涉及比较列表中的两个元素,我不确定使用for循环是否有效,如果它真的只是地图和平面图的糖。到目前为止,我有表达式的结构:

val points: List[(Double, Double)] = List((2.0,3.1),(3.5,2.3),(1.2,0.2),(6.4,2.4))
var minDistance = Double.PositiveInfinity
var closestPoints = ((Double.NaN, Double.NaN), (Double.NaN, Double.NaN))

for {
  point1 <- points
  point2 <- points if (point1 != point2) 
  if (distance(point1, point2) < minDistance): {
    minDistance = distance(point1, point2)
    closestPoints = (point1, point2)
  }
} yield (I guess I don't want a yield here?)

请注意,if (point1 != point2)并不是我想要的,因为我真的想要比较列表中的不同点,即使它们具有相同的值。这只能使用像

这样的东西
for {
  index1 <- 0 until points.length
  index2 <- 0 until index1
...

由于收益率,这仍然不能令人满意?我想有一些折叠实现可行,但我也不知道如何在内循环中迭代越来越小的子集。与简单的双循环相比,我发现foldLeft令人困惑。

2 个答案:

答案 0 :(得分:3)

您可以使用combinationsfoldLeft

来实现这一目标
points
  .combinations(2)
  .foldLeft((Double.PositiveInfinity,
    ((Double.NaN, Double.NaN), (Double.NaN, Double.NaN)))) { 
    case (acc, List(firstPoint, secondPoint)) =>
      val dist = distance(firstPoint, secondPoint)
      if (dist < acc._1) (dist, (firstPoint, secondPoint)) else acc
  }

如果您只关心这些点,而不是它们之间的实际距离,minBy可能不那么冗长:

points
  .combinations(2)
  .minBy { case List(first, second) => distance(first, second) }

答案 1 :(得分:1)

for{
    point1, i <- points.view.zipWithIndex
    point2, j <- points.view.zipWithIndex if( i > j)
    #add whatever you want to do next
}

但我会说

points.combinations(2).minBy{ pair => distance(pair(0), pair(1)) }

也可以。