Scala: получение промежуточных результатов сгиба - PullRequest
16 голосов
/ 17 декабря 2010

Я несколько раз сталкивался с проблемой поддержания состояния на протяжении операции с картой.Представьте себе следующую задачу:

Для заданного List [Int] сопоставьте каждый элемент с суммой всех предыдущих элементов и самого себя.
Таким образом, 1,2,3 становится 1, 1 + 2, 1 + 2+ 3.

Одно решение, которое я нашел, это:

scala> val a = 1 to 5                                                
a: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(1, 2, 3, 4, 5)

scala> a.foldLeft(List(0)){ case (l,i) => (l.head + i) :: l }.reverse
res3: List[Int] = List(0, 1, 3, 6, 10, 15)

Но почему-то я чувствую, что должно быть более простое решение.

Ответы [ 4 ]

31 голосов
/ 17 декабря 2010

Вы пытаетесь вычислить последовательность частичных сумм .

Общая операция для вычисления таких накоплений не fold, а scan, хотя scan выражается через fold в том виде, как вы показали (а fold фактически последний элемент списка, созданный scan).

Что касается Scala, я приведу пример

scala> scanLeft(List(1,2,3))(0)(_ + _)
res1: List[Int] = List(0, 1, 3, 6)
8 голосов
/ 17 декабря 2010

@ Дарио дал ответ, но просто добавил, что библиотека scala предоставляет scanLeft:

scala> List(1,2,3).scanLeft(0)(_ + _)
res26: List[Int] = List(0, 1, 3, 6)
7 голосов
/ 17 декабря 2010

Ответы scan являются лучшими, но стоит отметить, что можно сделать складку лучше и / или короче, чем в вашем вопросе. Во-первых, вам не нужно использовать сопоставление с образцом:

a.foldLeft(List(0)){ (l,i) => (l.head + i) :: l }.reverse

Во-вторых, обратите внимание, что foldLeft имеет сокращение:

(List(0) /: a){ (l,i) => (l.head + i) :: l }.reverse

В-третьих, обратите внимание, что при желании вы можете использовать коллекцию, которая может эффективно добавляться, чтобы вам не нужно было переворачиваться

(Vector(0) /: a){ (v,i) => v :+ (v.last + i) }

Так что, хотя это не так компактно, как scanLeft:

a.scanLeft(0)(_ + _)

все еще не так уж плохо.

6 голосов
/ 17 декабря 2010

Мне нравится складываться, как и всем, но менее точный ответ очень краткий и читаемый:

 a.map{var v=0; x=>{v+=x; v}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...