Команда ReQL: fold
Синтаксис команды
sequence.fold(base, function) → value sequence.fold(base, function, :emit => function[, :final_emit => function]) → sequence
Описание
Применяет функцию к последовательности по порядку, сохраняя состояние через накопитель. Команда fold возвращает либо единственное значение, либо новую последовательность.
В своём первом варианте, fold работает подобно команде reduce, возвращая значение, применяя комбинирующую функцию к каждому элементу в последовательности. Комбинирующая функция принимает два параметра: предыдущий результат сокращения (накопитель) и текущий элемент. Однако, fold имеет следующие отличия от reduce:
- гарантированно проходит по последовательности от первого элемента до последнего.
- передает начальное базовое значение в функцию с первым элементом вместо предыдущего результата сокращения.
combining_function(accumulator | base, element) → new_accumulator
Во втором варианте, fold работает подобно concat_map, возвращая новую последовательность вместо единственного значения. Когда предоставляется функция emit, fold будет:
- проходить по последовательности по порядку и принимать начальное базовое значение, как и выше.
- для каждого элемента в последовательности вызывать как комбинирующую функцию, так и отдельную функцию вывода. Функция вывода принимает три параметра: предыдущий результат сокращения (накопитель), текущий элемент и результат из комбинирующей функции (новое значение накопителя).
Если предоставляется функция вывода, она должна возвращать список.
emit(previous_accumulator, element, accumulator) → array
Также может быть предоставлена функция finalEmit, которая будет вызвана в конце последовательности. Она принимает один параметр: результат последнего сокращения по итерации (накопитель), или исходное базовое значение, если входная последовательность была пустой. Эта функция должна возвращать список, который будет добавлен в выходной поток fold.
final_emit(accumulator | base) → array
Пример: Объединение слов из списка.
r.table('words').order_by('id').fold('',
lambda { |acc, word| acc + r.branch(acc.eq(''), '', ', ') + word }
).run(conn)
(Этот пример можно реализовать с помощью reduce, но fold сохранит порядок, когда words является таблицей RethinkDB или другим потоком, что не гарантируется с reduce.)
Пример: Возвращение каждой второй строки в таблице.
r.table('players').fold(0,
lambda { |acc, row| acc + 1 },
:emit => lambda { |acc, row, new_acc| r.branch((new_acc % 2).eq(0), [row], []) }
).run(conn)
Первая функция увеличивает накопитель каждый раз при вызове, начиная с 0; вторая функция, функция вывода, поочерёдно возвращает список, содержащий текущую строку, или пустой список. Команда fold вернёт конкатенированный список каждого выведенного значения.
Пример: Вычисление пятидневного скользящего среднего для трекера веса.
r.table('tracker').filter({:name => 'bob'}).order_by('date')['weight'].fold(
[],
lambda { |acc, row| ([row] + acc).limit(5) },
:emit => lambda {
|acc, row, new_acc| r.branch(new_acc.size().eq(5), [new_acc.avg()], [])
}
).run(conn)
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/api/ruby/fold/