Home > Mobile >  Reducing iterator based on value
Reducing iterator based on value

Time:02-11

I have an iterator as such:

Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(7, 2020))

I'm trying to return an iterator, but with the values slightly changed. The values for all multiples of 5 must be added to the previous row. So the result would be:

Iterator(List(1, 2012), List(2, 4032), List(7, 2020))

I've tried using the following method:

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)

but it gives me the final value val aTransformed: List[Int] = List(1, 4029)

What can I do to get an iterator in my desired format? Is there a method to just check the previous/next row without folding it all into one final value?

I know this is possible by converting the iterator to a List, traversing, mutating and converting back to an iterator, but is there a more elegant solution?

Edit for clarification:

Consecutive multiples of 5 will get collated into one sum

Ex:

Iterator(List(1, 2012), List(2, 2015), List(5, 2017), List(10, 2025))

should become

Iterator(List(1, 2012), List(2, 6057))

CodePudding user response:

Following is a possible way to get the expected result. I haven't checked all the possibilities..

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

CodePudding user response:

Since we cant directly get last element from Iterator, we need a buffer to store the last element, and after calcuate, we check the buffer state and append it the final result.

Here I append a empty Iterator[List[Int]] element to simplify the check step.

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
    }

test

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))
  • Related