我有一个更新scala数组的任务:
val input = Seq[2, 1, 5, 4, 5, 1, 8, 4]
input
是需要更新的数组。 label
是索引,应该相应地更新数组中的元素。
元素的更新规则是
new_value = the_current_value + value_of_last_labeled_elements
例如,如果
val label = Seq(2)
那么期望的结果应该是
input = Seq(2,1,5,4,5,1,8,4)
output = Seq(2,1,5,9,10,6,13,9)
可能有多个标签:
val label = Seq(2,5)
然后期望的结果应该是:
input = Seq(2,1,5,4,5,1,8,4)
output = Seq(2,1,5,9,10,6,9,5)
第五个元素5被更改为6,因为最后标记的元素是5.从第六个元素开始,它们的值通过加1来更新,因为原始数组中的第五个元素是1。
我发现通过在循环中使用两个指针,可以在Java中轻松处理此任务。但是,我不知道Scala如何处理这个问题。
答案 0 :(得分:1)
scala> def shiftFromIndexBy (input: List[Int], toShiftFrom: List[Int], shiftBy: Int = 0) : List [Int] = (input, toShiftFrom) match {
| case (Nil, _) => Nil
| case (x :: xs, Nil) => input.map (_ + shiftBy)
| case (x :: xs, y:: ys) => if (y == 0) x + shiftBy :: shiftFromIndexBy (xs, ys.map (_ - 1), x) else
| x + shiftBy :: shiftFromIndexBy (xs, toShiftFrom.map(_ - 1), shiftBy)
| }
shiftFromIndexBy: (input: List[Int], toShiftFrom: List[Int], shiftBy: Int)List[Int]
scala> shiftFromIndexBy (input, label)
res19: List[Int] = List(2, 1, 5, 9, 10, 6, 13, 9)
scala> shiftFromIndexBy (input, List (2, 5))
res20: List[Int] = List(2, 1, 5, 9, 10, 6, 9, 5)
有3个案例,最后一个有两个子类。
对于大量输入和少量索引值,可以考虑计算一次使用shiftBy值进行变换并一次减小索引值的值的数量。但首先让事情发挥作用,然后让它们变得快速。
为方便起见,我使用了Lists,而不是Seq来实现。
答案 1 :(得分:1)
我想看看我是否可以在没有递归的情况下做到(当然,没有指针)。
def updateAfterIndex(input:Seq[Int], label: Seq[Int]): Seq[Int] = {
if (label.isEmpty) input
else {
val pad = Seq.fill(label.head + 1)(0) ++
(label :+ input.length - 1).sliding(2)
.flatMap { case Seq(a, b) => Seq.fill(b - a)(input(a)) }
input.zip(pad).map(t => t._1 + t._2)
}
}
它似乎适用于许多不良label
内容的例子,例如索引超出范围或顺序错误。
updateAfterIndex(Seq(2,1,5,4,5,1,8,4), Seq()) //res0: Seq[Int] = List(2, 1, 5, 4, 5, 1, 8, 4)
updateAfterIndex(Seq(2,1,5,4,5,1,8,4), Seq(2)) //res1: Seq[Int] = List(2, 1, 5, 9, 10, 6, 13, 9)
updateAfterIndex(Seq(2,1,5,4,5,1,8,4), Seq(2,5)) //res2: Seq[Int] = List(2, 1, 5, 9, 10, 6, 9, 5)
updateAfterIndex(Seq(2,1,5,4), Seq(5,2)) //res3: Seq[Int] = List(2, 1, 5, 4)