次の 2 つのシーケンスがあるとします。
val index = Seq(2,5,1,4,7,6,3)
val unsorted = Seq(7,6,5,4,3,2,1)
1 番目は、2 番目のソートに使用するインデックスです。私の現在の解決策は、インデックスをトラバースし、ソートされていないシーケンスから見つかった要素を使用して新しいシーケンスを構築することです。
val sorted = index.foldLeft(Seq[Int]()) { (s, num) =>
s ++ Seq(unsorted.find(_ == num).get)
}
しかし、この解決策は非常に非効率的でエラーが発生しやすいようです。反復ごとに、ソートされていない完全なシーケンスを検索します。また、インデックスと並べ替えられていないリストが同期していない場合は、エラーがスローされるか、要素が省略されます。どちらの場合も、順序付けられたシーケンスに非同期要素を追加する必要があります。
この問題に対するより効率的で確実な解決策はありますか? または、このパラダイムに適合するソートアルゴリズムはありますか?
注:これは構築例です。実際には、mongodb ドキュメントのリストをドキュメント ID の順序付きリストでソートしたいと考えています。
更新 1
Marius Danila からの回答を選択しました。これは、私の問題に対するより高速でスケーラなソリューションと思われるためです。同期されていないアイテムのソリューションは付属していませんが、これは簡単に実装できます。
したがって、更新されたソリューションは次のとおりです。
def sort[T: ClassTag, Key](index: Seq[Key], unsorted: Seq[T], key: T => Key): Seq[T] = {
val positionMapping = HashMap(index.zipWithIndex: _*)
val inSync = new Array[T](unsorted.size)
val notInSync = new ArrayBuffer[T]()
for (item <- unsorted) {
if (positionMapping.contains(key(item))) {
inSync(positionMapping(key(item))) = item
} else {
notInSync.append(item)
}
}
inSync.filterNot(_ == null) ++ notInSync
}
更新 2
Bask.cc によって提案されたアプローチは正しい答えのようです。また、同期していない問題も考慮されていませんが、これも簡単に実装できます。
val index: Seq[String]
val entities: Seq[Foo]
val idToEntityMap = entities.map(e => e.id -> e).toMap
val sorted = index.map(idToEntityMap)
val result = sorted ++ entities.filterNot(sorted.toSet)