scala: функционально накапливать переменную из коллекции (то есть без переменных) - PullRequest
15 голосов
/ 04 декабря 2011

это вопрос новичка

У меня есть следующий код:

var total = 0L
docs.foreach(total += _.length)

в документах у меня есть коллекция объектов со свойством .length

Я бы хотел что-то вроде:

val total = docs.[someScalaMethod](0, (element, acum) => acum + element.length )

Я имею в виду метод, который перебирает каждый элемент, передавая переменную-накопитель ...

Первый ноль, который я передаю, должен быть начальным значением переменной аккумулятора.

Как этого достичь?

Ответы [ 3 ]

22 голосов
/ 04 декабря 2011

Это называется фолдом. Это почти точно то, что вы заявили:

docs.foldLeft(0)((accum, element) => accum + element.length)

для версии, которая пересекает коллекцию слева направо (обычно предпочтительнее; справа налево - foldRight, а 2.9 имеет fold, который может начинаться где угодно, но имеет ограничения на то, как он может преобразовывать тип).

Как только вы привыкнете к этому, появляется сокращенная версия сгиба влево, где аккумулятор перемещается влево (представьте себе, что он проталкивается слева направо по списку), и вы используете заполнители для переменной имена, так как вы используете их только один раз каждый: (0 /: docs)(_ + _.length)

8 голосов
/ 04 декабря 2011
docs map { _.length } reduce { _ + _ }

или (спасибо Луиджи Плинге)

docs.map(_.length).sum
3 голосов
/ 05 декабря 2011

Вот версия Scalaz:

docs.foldMap(_.length)

Это эквивалентно docs.map(_.length).sum, но занимает всего один проход. Также работает со всеми моноидами .

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