2013-11-07 2 views
1

У меня есть коллекция, которую я хочу сопоставить с новой коллекцией, однако каждое результирующее значение зависит от значения до нее каким-то образом. Я мог бы решить это с помощью a leftFoldScala, крест между foldLeft и картой, поддерживающей ленивую оценку

val result:List[B] = (myList:List[A]).foldLeft(C -> List.empty[B]){ 
    case ((c, list), a) => 
    ..some function returning something like.. 
    C -> (B :: list) 
} 

Проблема здесь. Мне нужно выполнить итерацию по всему списку, чтобы получить результирующий список. Скажем, мне нужна функция, которая отображает TraversableOnce [A] в TraversableOnce [B] и оценивает только членов, как я их называю? Мне кажется, что это довольно обычная проблема, поэтому мне интересно, существует ли общий подход к этому. То, что я в настоящее время является:

implicit class TraversableOnceEx[T](val self : TraversableOnce[T]) extends AnyVal { 

    def foldyMappyFunction[A, U](a:A)(func:(A,T) => (A,U)):TraversableOnce[U] = { 
    var currentA = a 
    self.map { t => 
     val result = func(currentA, t) 
     currentA = result._1 
     result._2 
    } 
    } 
} 

Насколько функциональная чистота идет, вы не можете запустить его параллельно, но в остальном, кажется, звук.

Примером может быть; Верните мне каждый элемент, и если это первый элемент, который появился раньше.

val elements:TraversableOnce[E] 
val result = elements.mappyFoldyFunction(Set.empty[E]) { 
(s, e) => (s + e) -> (e -> s.contains(e)) 
} 
result:TraversableOnce[(E,Boolean)] 
+0

Не могли бы вы добавить пример вызова вашей 'foldyMappingFunction'? – david

+0

Я обновил пример –

ответ

1

Возможно, вы сможете использовать Государственную Монаду. Вот ваш пример, переписанный с использованием scalaz:

import scalaz._, Scalaz._ 

def foldyMappy(i: Int) = State[Set[Int], (Int, Boolean)](s => (s + i, (i, s contains(i)))) 

val r = List(1, 2, 3, 3, 6).traverseS(foldyMappy)(Set.empty[Int])._2 

//List((1,false), (2,false), (3,false), (3,true), (6,false)) 
println(r) 
0

Я действительно не понимаю ваш пример, как ваш чек содержит всегда будет приводить к false.

foldLeft - другой. Это приведет к одному значению, объединив все элементы списка. Вам явно нужен map (List =>List).

В любом случае, отвечая на ваш вопрос о лень: , вы должны использовать Stream вместо List. Stream не оценивает хвост, прежде чем называть его.

Stream API

+0

Или его аналог, который пытается не хранить себя в памяти после использования: Итератор –

0

Это выглядеть, как вам нужно SeqView. Используйте методы view или view(from: Int, until: Int) для создания нестрогого представления списка.

Смежные вопросы