这似乎是一个简单的场景,但我很难理解如何优雅/功能性地解决它。我有两个列表val pinnedStrings: Seq[(String, Int)]
和val fillerString: Seq[Int]
。我想合并它们,但每个固定的字符串保证在输出列表中的配对位置。如果我有:
val pinnedStrings = Seq("apple" -> 1, "banana" -> 4, "cherry" -> 6)
val fillerStrings = Seq("alpha", "bravo", "charlie", "delta", "echo", "foxtrot")
然后输出应为:
Seq("alpha", "apple", "bravo", "charlie", "banana", "delta", "cherry", "echo", "foxtrot")
让我们说如果没有足够的填充物到达固定字符串,我们会丢弃固定字符串。 (或者,如果将所有剩余的固定弦放在最后也更简单,那也很好。)
答案 0 :(得分:3)
或者:
scala> val pinnedStrings = Seq("apple" -> 1, "banana" -> 4, "cherry" -> 6)
pinnedStrings: Seq[(String, Int)] = List((apple,1), (banana,4), (cherry,6))
scala> val fillerStrings = Seq("alpha", "bravo", "charlie", "delta", "echo", "foxtrot")
fillerStrings: Seq[String] = List(alpha, bravo, charlie, delta, echo, foxtrot)
scala> (fillerStrings /: pinnedStrings) { case (acc, (s, i)) => ((acc take i) :+ s) ++ (acc drop i) }
res0: Seq[String] = List(alpha, apple, bravo, charlie, banana, delta, cherry, echo, foxtrot)
答案 1 :(得分:1)
我在写了这个问题之后解决了这个问题,但是因为我已经付出了努力,所以我想分享这个问题:
val pinnedStrings = Seq("apple" -> 1, "banana" -> 4, "cherry" -> 6)
val fillerStrings = Seq("alpha", "bravo", "charlie", "delta", "echo", "foxtrot")
// Preadjust the specified indices to account for earlier pinned strings
val pinnedStringsAdjusted = pinnedStrings.sortBy(_._2).zipWithIndex.map { case ((item, position), index) => (item, position - index) }
// Take advantage of the stability of `sortBy` to give pinned strings priority
(pinnedStrings ++ fillerStrings.zipWithIndex).sortBy(_._2).map(_._1)
// Output
// res5: Seq[String] = List(alpha, apple, bravo, charlie, banana, delta, cherry, echo, foxtrot)
如果两个固定字符串具有匹配的索引,则应该按预期工作用于相邻的固定索引,但会产生奇怪的行为。如果其他人也有想法,请打开其他选项。
答案 2 :(得分:1)
有时,如果用现有的集合组合器来实现某些东西感觉很麻烦,那么建议尝试直接递归实现。
这是一种方式:
def fill[A](pinned: List[(A, Int)], filler: List[A]): List[A] = {
def loop(pinned: List[(A, Int)], filler: List[A], i: Int, result: List[A]): List[A] = {
(pinned, filler) match {
case ((a, `i`) :: tail, _) => loop(tail.dropWhile(_._2 == i), filler, i + 1, a :: result)
case (_, (a :: tail)) => loop(pinned, tail, i + 1, a :: result)
case _ => result // no filler left
}
}
loop(pinned.sortBy(_._2), filler, 0, Nil).reverse
}
val pinnedStrings = List("apple" -> 1, "apple2" -> 1, "banana" -> 4, "cherry" -> 6)
val fillerStrings = List("alpha", "bravo", "charlie", "delta", "echo", "foxtrot")
fill(pinnedStrings, fillerStrings) // List(alpha, apple, bravo, charlie, banana, delta, cherry, echo, foxtrot)
请注意,它不需要对集合进行多次传递。