让我们假设我有以下两个序列:
val index = Seq(2,5,1,4,7,6,3)
val unsorted = Seq(7,6,5,4,3,2,1)
第一个是对第二个进行排序的索引。我目前的解决方案是遍历索引并使用未排序序列中找到的元素构造一个新序列。
val sorted = index.foldLeft(Seq[Int]()) { (s, num) =>
s ++ Seq(unsorted.find(_ == num).get)
}
但是这个解决方案对我来说似乎非常低效且容易出错。在每次迭代中,它都会搜索完整的未排序序列。如果索引和未排序列表不同步,那么要么会抛出错误,要么会省略一个元素。在这两种情况下,不同步的元素都应该附加到有序序列中。
有没有更有效和更可靠的解决方案来解决这个问题?或者是否有适合这种范式的排序算法?
注意:这是一个构造示例。实际上,我想按文档 ID 的有序列表对 mongodb 文档列表进行排序。
更新 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)