Scala: накапливать var из коллекции функциональным способом (то есть без vars)
Это вопрос новичков
У меня есть следующий код:
var total = 0L
docs.foreach(total += _.length)
в документах У меня есть коллекция объектов с свойством .length
Мне хотелось бы что-то вроде:
val total = docs.[someScalaMethod](0, (element, acum) => acum + element.length )
Я имею в виду метод, который выполняет итерацию каждого элемента, передающего переменную аккумулятора...
Первый нулевой проход я должен быть начальным значением аккумулятора var.
Как это можно достичь?
Ответы
Ответ 1
Это называется сгибом. Это почти то, что вы заявили:
docs.foldLeft(0)((accum, element) => accum + element.length)
для версии, которая перемещает коллекцию слева направо (обычно предпочтительнее, справа налево - foldRight
, а 2.9 имеет fold
, который может начинаться где угодно, но имеет ограничения на то, как он может преобразовать тип).
Как только вы привыкнете к этому, есть кратковременная версия складки влево, где аккумулятор идет слева (думайте, что он проталкивается слева направо через список), и вы используете заполнители для переменной имена, поскольку вы используете их только один раз: (0 /: docs)(_ + _.length)
Ответ 2
docs map { _.length } reduce { _ + _ }
или (спасибо переходит к Луиджи Плинге)
docs.map(_.length).sum
Ответ 3
Вот версия Scalaz:
docs.foldMap(_.length)
Это эквивалентно docs.map(_.length).sum
, но занимает всего один проход. Кроме того, работает со всеми monoids.