Как мне объединить эти наборы массивов, чтобы они были объединены вместе и не было повторяющихся значений?
Не уверен, что у lodash есть что-то, чтобы помочь с этим, большинство других ответов, которые я нашел, основаны на том, что массивы являются плоскими, но в этой структуре моего набора данных они вложены.
Спасибо за вашу помощь!
let arr1 = [
["name", "id", 'age'],
["Susan", "3", '20'],
["John", "1", '21'],
["Bob", "2", '23'],
["Ben", "4", '20']
];
let arr2 = [
["name", "id", 'height'],
["Bob", "2", '50'],
["John", "1", '45'],
["Ben", "4", '43'],
["Susan", "3", '48'],
];
let arr3 = [
["name", "id", 'parent'],
["Bob", "2", 'yes'],
["John", "1", 'yes'],
];
//desired output
// [
// ['name', 'id', 'age', 'height', 'parent'],
// ["Susan", "3", '20', '48', ''],
// ["John", "1", '21', '45', 'yes'],
// ["Bob", "2", '23', '50', 'yes'],
// ["Ben", "4", '20', '43', '']
// ]
Используя lodash flatten и uniq
Flatten объединяет массивы в сглаженный массив.
_.uniq(_.flatten([arr1, arr2, arr2));
Теперь это отвечает на заголовок и текст вашего вопроса, но, судя по желаемому результату, вас ждут тяжелые времена. То, что я изложил, не даст такого результата.
Вы можете изучить функцию Lodash merge
, но то, что вы делаете, намного проще делать с объектами, а не с массивами.
Рассматривали ли вы возможность превратить имеющиеся у вас массивы в объекты? Лучше всего сделать это, а затем использовать lodash mergeWith
.
Объедините таблицы, преобразовав строки в объекты и объединив их с помощью Array.reduce()
и карты (чтобы сохранить исходный порядок). Сохраните заголовки и объедините их с помощью _.union()
(или набора). Затем верните массив, содержащий комбинированные заголовки, а строки основного текста преобразуются в массивы с помощью Array.mpa()
и комбинированных заголовков.
// convert table rows to objects
const tableRowsToObjects = ([head, ...body]) => [head, body.map(row => _.zipObject(head, row))]
// combine tables' headers & bodies
const combineTables = tables => {
const header = _.union(..._.map(tables, _.head))
const body = Array.from(
tables
.flatMap(([, rows]) => rows)
.reduce((acc, row) => acc.set(row.id, { ...acc.get(row.id), ...row }), new Map)
.values()
)
return [header, body]
}
// convert tables to objects, merge them, and then convert back to rows
const mergeTables = (...tables) => {
const [header, body] = combineTables(tables.map(tableRowsToObjects))
return [
header,
...body.map(row => header.map(col => row[col] ?? ''))
];
}
const arr1 = [["name","id","age"],["Susan","3","20"],["John","1","21"],["Bob","2","23"],["Ben","4","20"]];
const arr2 = [["name","id","height"],["Bob","2","50"],["John","1","45"],["Ben","4","43"],["Susan","3","48"]];
const arr3 = [["name","id","parent"],["Bob","2","yes"],["John","1","yes"]];
const result = mergeTables(arr1, arr2, arr3);
console.info(result);
<script src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity = "sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww= = " crossorigin = "anonymous"></script>
Вы можете сделать это в ванильном JavaScript. Сначала превратите все три массива в объект, используя метод сокращения. Затем снова с помощью метода сокращения получите уникальный объединенный объект. Наконец, сделайте объект массивом.
const arr1 = [
['name', 'id', 'age'],
['Susan', '3', '20'],
['John', '1', '21'],
['Bob', '2', '23'],
['Ben', '4', '20'],
];
const arr2 = [
['name', 'id', 'height'],
['Bob', '2', '50'],
['John', '1', '45'],
['Ben', '4', '43'],
['Susan', '3', '48'],
];
const arr3 = [
['name', 'id', 'parent'],
['Bob', '2', 'yes'],
['John', '1', 'yes'],
];
const makeObject = (arr) => {
const props = arr.slice(0, 1).flat();
return arr.slice(1).map((x) => {
return props.reduce((prev, c, i) => {
const p = prev;
p[c] = x[i];
return p;
}, {});
});
};
const objArray = Object.values(
[...makeObject(arr1), ...makeObject(arr2), ...makeObject(arr3)].reduce(
(prev, c) => {
const p = prev;
const key = c.id;
if (!p[key])
p[key] = {
...{ name: '', id: '', age: '', height: '', parent: '' },
...c,
};
else p[key] = { ...p[key], ...c };
return p;
},
{}
)
);
const ret = objArray.map((x) => Object.values(x));
ret.unshift(Object.keys(objArray[0]));
console.info(ret);
Я предлагаю сначала создать объект. Синтаксис ES6 позволяет сделать это в несколько строк. Это также решает проблему унификации.
const addData = ([head, ...data], obj = {}) => (
data.reduce((acc, [name, id, value]) => ({
...acc,
[id]: {
...acc[id],
name, [head[2]]: value
}
}), obj)
)
// -------
const arr1 = [
["name", "id", 'age'],
["Susan", "3", '20'],
["John", "1", '21'],
["Bob", "2", '23'],
["Ben", "4", '20']
];
const arr2 = [
["name", "id", 'height'],
["Bob", "2", '50'],
["John", "1", '45'],
["Ben", "4", '43'],
["Susan", "3", '48'],
];
const arr3 = [
["name", "id", 'parent'],
["Bob", "2", 'yes'],
["John", "1", 'yes'],
];
let indexedObj = {}
indexedObj = addData(arr1, indexedObj)
indexedObj = addData(arr2, indexedObj)
indexedObj = addData(arr3, indexedObj)
console.info(indexedObj)
Затем используйте метод создания массива mr hr.
Я согласен с вами... это будет тяжело 😰