В Mongo 3.6 существует функция mergeObjects, которая делает именно то, что вам нужно:
https://docs.mongodb.com/manual/reference/operator/aggregation/mergeObjects/
Предоставленный код представляет собой функцию сокращения, которая принимает три параметра - функцию, которая отображает входные данные типа 'a
и 'b
на выходные данные типа 'b
, значение типа 'b
и в виде списка элементов типа 'a
.
Например, пример length
из лекции:
let length (lst: int list) : int =
reduce (fun _ len -> len + 1) 0 lst
Первый параметр для reduce
- это функция, которая при задании двух параметров отбрасывает первый и возвращает второй параметр увеличивается на единицу. Второе значение (0), которое будет использоваться в качестве аккумулятора. Третий список, чтобы найти длину.
Поведение этой рекурсивной функции reduce
состоит в том, чтобы возвращать второй параметр (аккумулятор, используемый в примере длины), как только предоставленный список пуст, и в противном случае запустить предоставленную функцию, используя заголовок списка и рекурсивный значение.
Еще раз перейдя к примеру length
, скажем, мы даем ему список с одним элементом [1]
.
Наш вызов length
становится reduce (fun _ len -> len + 1) 0 [1]
Напомним reduce
:
let rec reduce (f:'a -> 'b -> 'b) (u:'b) (xs:'a list) : 'b =
match xs with
| [] -> u
| hd::tl -> f hd (reduce f u tl);;
Сначала мы сопоставляем [1]
с []
, что не удается , Поскольку это непустой список, мы запускаем f hd (reduce f u tl)
Напомним, что f
- это параметр, предоставленный length
: fun _ len -> len + 1
Поэтому мы эффективно запускаем следующее :
(fun _ len -> len + 1) 1 (reduce (fun _ len -> len + 1) 0 [])
В этом случае функция length
отбрасывает первый параметр, поскольку значения в списке не обязательны для определения длины списка.
Рекурсивная часть будет сопоставлена с []
и вернет значение u
в то время, которое равно 0.
Следовательно, на один уровень выше, (fun _ len -> len + 1) 1 (reduce (fun _ len -> len + 1) 0 [])
становится (fun _ len -> len + 1) 1 0
и возвращается [ 1128], что упрощает наше ожидаемое значение 1, которое представляет длину списка.
Теперь ко второму вопросу, касающемуся times_x
. Это выполняет сопоставление. Например, мы можем отобразить [1;2;3;4;5]
в [3;6;9;12;15]
с отображением fun x -> x * 3
.
Здесь times_x
определяется следующим образом:
let times_x (x: int) (lst: int list) : int list =
map (fun y -> y*x) lst
times_x
принимает целое число и список. Используя приведенный выше пример, мы можем вызвать его с помощью times_x 3 [1;2;3;4;5]
, чтобы получить [3;6;9;12;15]
.
Помимо этого, я рекомендую изучить, как работают функции map и Reduce в целом.
Я надеюсь, что этот ответ был адекватен при решении вашего вопроса.