基于值减少迭代器
Reducing iterator based on value
我有一个这样的迭代器:
Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(7, 2020))
我正在尝试 return 一个迭代器,但值略有改变。所有 5 的倍数的值都必须添加到上一行。所以结果将是:
Iterator(List(1, 2012), List(2, 4032), List(7, 2020))
我试过使用以下方法:
val a = Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(7, 2020))
val aTransformed = a.reduce((x,y) => if (y(0)%5 == 0) List(x(0),x(1)+y(1)) else x)
但它给了我最终的价值val aTransformed: List[Int] = List(1, 4029)
如何获得所需格式的迭代器?有没有一种方法可以只检查 previous/next 行而不将其全部折叠成一个最终值?
我知道这可以通过将迭代器转换为列表、遍历、变异并转换回迭代器来实现,但是有没有更优雅的解决方案?
编辑澄清:
5的连续倍数将合并为一个总和
例如:
Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(10, 2025))
应该变成
Iterator(List(1, 2012), List(2, 6057))
以下是获得预期结果的可能方法。我还没有检查所有的可能性..
val interResult = itr.foldLeft((List.empty[List[Int]], List.empty[Int])) { (acc, curr) =>
if(curr.size != 2)
acc
else if(acc._2.isEmpty)
(acc._1, curr)
else
if(curr.headOption.exists(_ % 5 == 0))
(acc._1, List(acc._2.head, acc._2.last + curr.last))
else
(acc._1 :+ acc._2, curr)
}
interResult._1 :+ interResult._2
由于我们不能直接从Iterator
中获取最后一个元素,我们需要一个缓冲区来存储最后一个元素,并且在计算之后,我们检查缓冲区状态并将其附加到最终结果。
这里我附加了一个空的 Iterator[List[Int]]
元素来简化检查步骤。
def convert(xs: Iterator[List[Int]]): Iterator[List[Int]] = {
val res = (xs ++ Iterator(List[Int]())).foldLeft(Iterator[List[Int]](), List[Int]())((x, y)=> {
if (y.nonEmpty && y(0) % 5 == 0) {
if (x._2.nonEmpty) {
(x._1, List(x._2(0), x._2(1) + y(1)))
} else {
(x._1, y)
}
} else {
if (x._2.nonEmpty) {
(x._1 ++ Iterator(x._2), y)
} else {
(x._1, y)
}
}
})
res._1
}
测试
scala> val xs1 = Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(7, 2020))
val xs1: Iterator[List[Int]] = <iterator>
scala> val xs2 = Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(10, 2025))
val xs2: Iterator[List[Int]] = <iterator>
scala> convert(xs1)
val res44: Iterator[List[Int]] = <iterator>
scala> res44.toList
val res45: List[List[Int]] = List(List(1, 2012), List(2, 4032), List(7, 2020))
scala> convert(xs2)
val res47: Iterator[List[Int]] = <iterator>
scala> res47.toList
val res48: List[List[Int]] = List(List(1, 2012), List(2, 6057))
我有一个这样的迭代器:
Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(7, 2020))
我正在尝试 return 一个迭代器,但值略有改变。所有 5 的倍数的值都必须添加到上一行。所以结果将是:
Iterator(List(1, 2012), List(2, 4032), List(7, 2020))
我试过使用以下方法:
val a = Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(7, 2020))
val aTransformed = a.reduce((x,y) => if (y(0)%5 == 0) List(x(0),x(1)+y(1)) else x)
但它给了我最终的价值val aTransformed: List[Int] = List(1, 4029)
如何获得所需格式的迭代器?有没有一种方法可以只检查 previous/next 行而不将其全部折叠成一个最终值?
我知道这可以通过将迭代器转换为列表、遍历、变异并转换回迭代器来实现,但是有没有更优雅的解决方案?
编辑澄清:
5的连续倍数将合并为一个总和
例如:
Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(10, 2025))
应该变成
Iterator(List(1, 2012), List(2, 6057))
以下是获得预期结果的可能方法。我还没有检查所有的可能性..
val interResult = itr.foldLeft((List.empty[List[Int]], List.empty[Int])) { (acc, curr) =>
if(curr.size != 2)
acc
else if(acc._2.isEmpty)
(acc._1, curr)
else
if(curr.headOption.exists(_ % 5 == 0))
(acc._1, List(acc._2.head, acc._2.last + curr.last))
else
(acc._1 :+ acc._2, curr)
}
interResult._1 :+ interResult._2
由于我们不能直接从Iterator
中获取最后一个元素,我们需要一个缓冲区来存储最后一个元素,并且在计算之后,我们检查缓冲区状态并将其附加到最终结果。
这里我附加了一个空的 Iterator[List[Int]]
元素来简化检查步骤。
def convert(xs: Iterator[List[Int]]): Iterator[List[Int]] = {
val res = (xs ++ Iterator(List[Int]())).foldLeft(Iterator[List[Int]](), List[Int]())((x, y)=> {
if (y.nonEmpty && y(0) % 5 == 0) {
if (x._2.nonEmpty) {
(x._1, List(x._2(0), x._2(1) + y(1)))
} else {
(x._1, y)
}
} else {
if (x._2.nonEmpty) {
(x._1 ++ Iterator(x._2), y)
} else {
(x._1, y)
}
}
})
res._1
}
测试
scala> val xs1 = Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(7, 2020))
val xs1: Iterator[List[Int]] = <iterator>
scala> val xs2 = Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(10, 2025))
val xs2: Iterator[List[Int]] = <iterator>
scala> convert(xs1)
val res44: Iterator[List[Int]] = <iterator>
scala> res44.toList
val res45: List[List[Int]] = List(List(1, 2012), List(2, 4032), List(7, 2020))
scala> convert(xs2)
val res47: Iterator[List[Int]] = <iterator>
scala> res47.toList
val res48: List[List[Int]] = List(List(1, 2012), List(2, 6057))