Scala, расширяющий итератор - PullRequest
10 голосов
/ 17 февраля 2012

Я рассчитываю расширить итератор для создания нового метода takeWhileInclusive, который будет работать как takeWhile, но будет включать в себя последний элемент.

Моя проблема заключается в том, что лучше всего расширять итератор для возвратановый итератор, который я бы хотел оценить ленивым.Исходя из фона C #, я обычно использую IEnumerable и использую ключевое слово yield, но такой опции не существует в Scala.

например, у меня может быть

List(0,1,2,3,4,5,6,7).iterator.map(complex time consuming algorithm).takeWhileInclusive(_ < 6)

, поэтому в этом случае takeWhileInclusive будет разрешать предикат только для значений, пока я не получу результат больше 6, и он будет включать этот первый результат

, пока у меня есть:

object ImplicitIterator {
  implicit def extendIterator(i : Iterator[Any]) = new IteratorExtension(i)
}

class IteratorExtension[T <: Any](i : Iterator[T]) {
  def takeWhileInclusive(predicate:(T) => Boolean) = ?
}

Ответы [ 5 ]

11 голосов
/ 17 февраля 2012

Вы можете использовать span метод Iterator, чтобы сделать это довольно чисто:

class IteratorExtension[A](i : Iterator[A]) {
  def takeWhileInclusive(p: A => Boolean) = {
    val (a, b) = i.span(p)
    a ++ (if (b.hasNext) Some(b.next) else None)
  }
}

object ImplicitIterator {
  implicit def extendIterator[A](i : Iterator[A]) = new IteratorExtension(i)
}

import ImplicitIterator._

Теперь (0 until 10).toIterator.takeWhileInclusive(_ < 4).toList дает List(0, 1, 2, 3, 4), например.

7 голосов
/ 17 февраля 2012

Это один случай, когда я нахожу изменяемое решение превосходным:

class InclusiveIterator[A](ia: Iterator[A]) {
  def takeWhileInclusive(p: A => Boolean) = {
    var done = false
    val p2 = (a: A) => !done && { if (!p(a)) done=true; true }
    ia.takeWhile(p2)
  }
}
implicit def iterator_can_include[A](ia: Iterator[A]) = new InclusiveIterator(ia)
3 голосов
/ 18 февраля 2012

Для получения fold на кортеже требуется скаляр (A, B)

scala> implicit def Iterator_Is_TWI[A](itr: Iterator[A]) = new { 
     | def takeWhileIncl(p: A => Boolean) 
     |   = itr span p fold (_ ++ _.toStream.headOption)
     | }
Iterator_Is_TWI: [A](itr: Iterator[A])java.lang.Object{def takeWhileIncl(p: A => Boolean): Iterator[A]}

Вот оно на работе:

scala> List(1, 2, 3, 4, 5).iterator takeWhileIncl (_ < 4)
res0: Iterator[Int] = non-empty iterator

scala> res0.toList
res1: List[Int] = List(1, 2, 3, 4)

Вы можете перевернуть свой собственный фолд напара, как это:

scala> implicit def Pair_Is_Foldable[A, B](pair: (A, B)) = new { 
    |    def fold[C](f: (A, B) => C): C = f.tupled(pair) 
    |  } 
Pair_Is_Foldable: [A, B](pair: (A, B))java.lang.Object{def fold[C](f: (A, B) => C): C}
2 голосов
/ 17 февраля 2012
class IteratorExtension[T](i : Iterator[T]) {
  def takeWhileInclusive(predicate:(T) => Boolean) = new Iterator[T] {
    val it = i
    var isLastRead = false

    def hasNext = it.hasNext && !isLastRead
    def next = {
      val res = it.next
      isLastRead = !predicate(res)
      res
    }
  }
}

И есть ошибка в вашем неявном.Вот это исправлено:

object ImplicitIterator {
  implicit def extendIterator[T](i : Iterator[T]) = new IteratorExtension(i)
}
0 голосов
/ 17 февраля 2012
scala> List(0,1,2,3,4,5,6,7).toStream.filter (_ < 6).take(2)
res8: scala.collection.immutable.Stream[Int] = Stream(0, ?)

scala> res8.toList 
res9: List[Int] = List(0, 1)

После вашего обновления:

scala> def timeConsumeDummy (n: Int): Int = {
     | println ("Time flies like an arrow ...") 
     | n }
timeConsumeDummy: (n: Int)Int

scala> List(0,1,2,3,4,5,6,7).toStream.filter (x => timeConsumeDummy (x) < 6) 
Time flies like an arrow ...
res14: scala.collection.immutable.Stream[Int] = Stream(0, ?)

scala> res14.take (4).toList 
Time flies like an arrow ...
Time flies like an arrow ...
Time flies like an arrow ...
res15: List[Int] = List(0, 1, 2, 3)

timeConsumeDummy вызывается 4 раза.Я что-то пропустил?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...