2016-09-10 17 views
2

リスト内で最も近い2つのペアを見つけるための簡単な関数を作成しようとしています。この操作ではリストの2つの要素を比較する必要があるため、実際にマップとフラットマップの単なる砂糖であれば、forループを使用するかどうかはわかりません。私は本当に彼らが同じであっても、リスト内の個別のポイントを比較したいので、if (point1 != point2)は、私がここに欲しいものは本当にないことを倍精度浮動小数点型ループの内部インデックスを増やす

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

注:これまでのところ、私はこのよう式の構造を持っています値。

for { 
    index1 <- 0 until points.length 
    index2 <- 0 until index1 
... 

これはまだ収率が悪いと思われますか?私はいくつかのfoldleftの実装が動作すると思いますが、私はまた、内側のループのより小さいサブセットに対してどのように反復するのか分かりません。 foldLeftは単純な二重ループに比べて推論するのが混乱していることがわかります。

答えて

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

'foldLeft'の2番目のパラメータのまわりで'() 'ではなく' {} 'を使わずに私のためにコンパイルしません。また、 '{case(acc、List(firstPoint、secondPoint))=> {'は引数を解く方がややはっきりしていますか? –

+0

@TheArchetypalPaul括弧がありませんでした。しかし、あなたの提案は間違いなくきれいで、編集されています。 –

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

も同様です。

関連する問題