Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating in Scala: checking previous values

I am having the following iterator:

val it = Iterator(("a",5),("a",3),("a",2),("a",1),("b",8),("b",2),("b",1),("c",1))

The values inside are sorted firstly by the first element(String) and secondly by the second(Int). How can I get the first 2 values from each 'letter'. So the result should be in that example:

Iterator(("a",5),("a",3),("b",8),("b",2),("c",1))

It can be done with groupBy:

it.toList.groupBy(_._1).mapValues(_.take(2)).values.flatten.toIterator

but I would like to see a solution which goes through each element and check the previous 'string' element and if its the same and the 'count' is less than 2 then it yield this value.

Edit:

Following the logic of @jwvh answer: How can it be generalized to take the first N values instead of the first 2?

like image 874
Mpizos Dimitris Avatar asked Dec 19 '22 14:12

Mpizos Dimitris


2 Answers

It might be nice if we didn't have to consume the entire iterator all at once.

UPDATED

case class LimitItr[A,B](var itr: Iterator[(A,B)], reps:Int) extends Iterator[(A,B)] {
  private var memory: List[A] = List()
  def hasNext = itr.hasNext
  def next() = {
    val current = itr.next
    if (!memory.headOption.contains(current._1))
      memory = List()
    memory = current._1 :: memory
    if (memory.length >= reps) {
      itr = itr.dropWhile(_._1 == memory.head)
      itr.hasNext  // force the iterator forward
    }
    current
  }
}

Usage:

val repLimitedItr = LimitItr(itrOfTuples, numOfRepetitionsAllowed)
like image 98
jwvh Avatar answered Dec 28 '22 08:12

jwvh


You could use a fold operation, but it is more cumbersome than your solution:

val result = it.foldLeft((Seq[(String, Int)](), "", 0)){
  case ((acc, prev, count), (l, n)) =>
    if (prev == l) {
      if (count < 2) (acc :+ (l, n), prev, count + 1)
      else (acc, prev, count + 1)
    }
    else (acc :+ (l, n), l, 1)
}

println(result._1)
like image 34
devkat Avatar answered Dec 28 '22 07:12

devkat