У меня есть два массива объектов, которые я хочу "Full Outer Join", как в SQL:
Набор данных A:
[ { id: 1, name: "apple", color: "red" }, {id: 2, name: "banana", color: "yellow"} ]
Набор данных B:
[ { id: 1, name: "apple", color: "blue" }, {id: 3, name: "mango", color: "green"} ]
Ожидаемый результат:
[ { id: 1, dataset_a: { id: 1, name: "apple", color: "red" }
, dataset_b: { id: 1, name: "apple", color: "blue" }
}
, { id: 2, dataset_a: { id: 2, name: "banana", color: "yellow"}
, dataset_b: null
}
, { id: 3, dataset_a: null
, dataset_b: { id: 3, name: "mango", color: "green"}
}
]
- Идентификаторы уникальны.
- Может использоваться Loda sh.
- У меня нет ограничений на Версия ES.
Вместо нуля пустой объект тоже будет в порядке. Идентификаторы не обязательно должны повторяться, как показано ниже. Итак, это было бы так же хорошо:
[ { id: 1, dataset_a: { name: "apple", color: "red" }
, dataset_b: { name: "apple", color: "blue" }
}
, { id: 2, dataset_a: { name: "banana", color: "yellow"}
, dataset_b: {}
}
, { id: 3, dataset_a: {}
, dataset_b: { name: "mango", color: "green"}
}
]
Решение Нины Шольц, преобразованное в функцию:
fullOuterJoin(dataset_a_name, dataset_b_name, dataset_a, dataset_b, key) {
const getNullProperties = keys => Object.fromEntries(keys.map(k => [k, null]));
var data = { [dataset_a_name]:dataset_a, [dataset_b_name]:dataset_b },
result = Object
.entries(data)
.reduce((r, [table, rows]) => {
//forEach dynamic destructuring
rows.forEach(({ [key]:id, ...row }) => {
if (!r[id]) r.items.push(r[id] = { [key]:id, ...getNullProperties(r.tables) });
r[id][table] = row;
});
r.tables.push(table);
r.items.forEach(item => r.tables.forEach(t => item[t] = item[t] || null));
return r;
}, { tables: [], items: [] })
.items;
return result;
},