Столкнувшись с подобными проблемами, я всегда стараюсь разбить их на более общие шаги Для этого конкретного случая есть четыре:
1. Группировка по id
Вы упоминаете, что хотите присоединиться к элементам по id. Давайте начнем с сортировки записей по идентификатору.
Общий пример
Вот пример groupBy
:
const groupById = xs =>
xs.reduce(
(acc, x) => {
if (!acc[x.id]) acc[x.id] = [];
acc[x.id].push(x);
return acc;
},
{}
);
console.log(
groupById(
[{ id: 1, a: 1 }, { id: 1, b: 2 }, { id: 2, a: 1 } ]
)
);
Если код сложен для понимания, взгляните на некоторые ответы «как сгруппировать массив объектов по свойству» здесь при переполнении стека.
Применительно к вашим данным
var names = [
{id:'1', age:18, name:'Jaden'},
{id:'2', age:19, name:'Mark'},
{id:'3', age:38, name:'Jackson'}
];
var jobs = [
{id:'1', job: 'webDev'},
{id:'1', job: 'webDev2'},
{id:'2', job: 'CEO'}
];
var births = [
{id:'1', birth: '2000/02/01'},
{id:'2', birth: '1999/05/12'},
{id:'3', birth: '1982/05/12'}
];
console.log(
groupById(names),
groupById(jobs),
groupById(births)
)
function groupById(xs) {
return xs.reduce(
(acc, x) => {
if (!acc[x.id]) acc[x.id] = [];
acc[x.id].push(x);
return acc;
},
{}
);
};
Заметьте, как большинство групп (массивов) имеют только один элемент? Только объект заданий имеет группу из двух заданий. Тем не менее, важно, чтобы все группы имели одинаковый формат: массив.
2. Слияние имени, возраста, работы и рождения.
Теперь, когда у нас есть группы элементов, к которым можно обратиться по их идентификатору, мы можем начать думать о их объединении.
Общий пример
В Javascript есть логика для объединения встроенных объектов! Это Object.assign
:
console.log(
Object.assign(
{ },
{ a: 1 },
{ b: 2 },
{ c: 3, d: 4 }
)
);
Применительно к вашим данным:
console.log(
Object.assign(
{ id: null, age: null, name: null, job: null },
{ id:'1', age:18, name:'Jaden'},
{ id:'1', job: 'webDev'},
{ id:'1', birth: '2000/02/01'}
)
);
Обратите внимание, что мы использовали нового пустого человека в качестве первого параметра, чтобы обеспечить наличие всех свойств!
3. Создание «лишних» записей
Теперь, когда мы выяснили первый и последний шаг, нам нужно придумать наборы объектов, которые должны быть объединены. Первый шаг: сгруппируйте все данные, которые мы имеем для определенного человека. Давайте сделаем массив с идентификатором "1"
:
const dataForPerson1 = [ namesAndAges["1"], jobs["1"], births["1"] ];
Теперь у нас есть вложенный массив:
[
[ { name: "Jaden", ... } ],
[ { job: "webDev", ... }, { job: "webDev2", ... } ],
[ { birth: "1998/02/01" } ]
]
Для этого массива нам нужно сделать возможными все комбинации трех объектов. К счастью, это опять то, что можно «абстрагировать» в общий шаг:
Общий пример
const combinations = (xs, ys) =>
xs.reduce(
(cs, x) => cs.concat(ys.map(y => [y].concat(x))),
[]
);
console.log(
[ ["a"], ["b1", "b2"], ["c"] ]
.reduce(combinations)
)
Обратите внимание, как мы переходим от четырех записей, разбросанных по трем массивам, к двум комбинациям записей.
Применительно к вашим данным:
const combinations = (xs, ys) =>
xs.reduce(
(cs, x) => cs.concat(ys.map(y => [y].concat(x))),
[]
);
console.log(JSON.stringify(
[
[ {id:'1', age:18, name:'Jaden'} ],
[ {id:'1', job: 'webDev'},
{id:'1', job: 'webDev2'} ],
[ {id:'1', birth: '2000/02/01'} ]
].reduce(combinations)
,null, 2));
Если вы внимательно посмотрите на результат, вы увидите, что правильный результат начинает обретать форму!
4. Цикл по всем данным и автоматическая генерация результата
Здесь все это объединяется. Суммировано ( Жирный шагов добавлено):
- Начните с трех массивов
- Сгруппируйте каждый массив по
id
property (1)
- Цикл по всем найденным
id
значениям для поиска групп записей (4)
- Создание всех комбинаций (3)
- Присоединить каждую запись к одному объекту (2)
Обратите внимание, что большая часть кода не относится к вашему приложению или данным. Конвейер, который мы создаем со ссылками на данные, - это то, что в конечном итоге выполняет конкретную работу!
// GENERIC UTILITIES
const groupById = xs =>
xs.reduce(
(acc, x) => {
if (!acc[x.id]) acc[x.id] = [];
acc[x.id].push(x);
return acc;
},
{}
);
const combinations = (xs, ys) =>
xs.reduce(
(cs, x) => cs.concat(ys.map(y => [y].concat(x))),
[]
);
const allCombinations = xxs => xxs.length === 1
? xxs
: xxs.reduce(combinations);
const merge = proto => obs => Object.assign(
{}, proto,
...obs
);
// OUR DATA
const names = groupById([
{id:'1', age:18, name:'Jaden'},
{id:'2', age:19, name:'Mark'},
{id:'3', age:38, name:'Jackson'}
]);
const jobs = groupById([
{id:'1', job: 'webDev'},
{id:'1', job: 'webDev2'},
{id:'2', job: 'CEO'}
]);
const births = groupById([
{id:'1', birth: '2000/02/01'},
{id:'2', birth: '1999/05/12'},
{id:'3', birth: '1982/05/12'}
]);
// DATA SPECIFIC HELPERS
const join = id => [ names[id], jobs[id], births[id] ].filter(x => x);
const allIds = new Set([
...Object.keys(names),
...Object.keys(jobs),
...Object.keys(births)
]);
// OUR APP
const result = Array.from(allIds)
.map(join)
.map(allCombinations)
.reduce((xs, ys) => xs.concat(ys)) // flatten
.map(merge({ id: null, age: null, name: null, birth: null, job: null }))
console.log(result);
.as-console-wrapper { min-height: 100%; }