Я пытаюсь найти лучший / самый эффективный или наиболее функциональный способ сравнения / объединения / манипулирования двумя массивами (списками) одновременно в JS.
Пример, который я привожу нижеэто простой пример общей концепции.В моем текущем проекте я имею дело с очень сумасшедшим отображением списков, фильтрацией и т. Д. С очень большими списками объектов.
Как указано ниже, моей первой идеей (version1
) по сравнению списков было бы запуститьчерез первый список (т. е. карту) и в функции анонимного / обратного вызова отфильтруйте второй список, чтобы он соответствовал критериям, необходимым для сравнения (например, идентификаторы соответствия).Это, очевидно, работает, как в version1
ниже.
У меня возник вопрос с точки зрения производительности, так как с помощью этого метода на каждой итерации / вызове карты весь 2-й список фильтруется только для того, чтобы найти этот один элемент, которыйсоответствует фильтру.
Кроме того, фильтр пропускает все остальные элементы в списке list2, которые должны совпадать в списке list1.Значение (поскольку это предложение, вероятно, не имело смысла):
list1.map list2.filter
id:1 [id:3,id:2,id:1]
^-match
id:2 [id:3,id:2,id:1]
^-match
id:3 [id:3,id:2,id:1]
^-match
В идеале на первой итерации карты (list1 id:1
), когда фильтр встречает list2 id:3
(первый элемент), он просто соответствует емуна list1 id:3
Думая с вышеупомянутой концепцией (в соответствии с более поздним идентификатором, когда он встречался ранее, я придумал version2
).
Это превращает list2 всловарь, а затем ищет значение в любой последовательности по ключу.
const list1 = [
{id: '1',init:'init1'},
{id: '2',init:'init2'},
{id: '3',init:'init3'}
];
const list2 = [
{id: '2',data:'data2'},
{id: '3',data:'data3'},
{id: '4',data:'data4'}
];
/* ---------
* version 1
*/
const mergedV1 = list1.map(n => (
{...n,...list2.filter(f => f.id===n.id)[0]}
));
/* [
{"id": "1", "init": "init1"},
{"id": "2", "init": "init2", "data": "data2"},
{"id": "3", "init": "init3", "data": "data3"}
] */
/* ---------
* version 2
*/
const dictList2 = list2.reduce((dict,item) => (dict[item.id]=item,dict),{});
// does not handle duplicate ids but I think that's
// outside the context of this question.
const mergedV2 = list1.map(n => ({...n,...dictList2[n.id]}));
/* [
{"id": "1", "init": "init1"},
{"id": "2", "init": "init2", "data": "data2"},
{"id": "3", "init": "init3", "data": "data3"}
] */
JSON.stringify(mergedV1) === JSON.stringify(mergedV2);
// true
// and just for fun
const sqlLeftOuterJoinInJS = list1 => list2 => on => {
const dict = list2.reduce((dict,item) => (
dict[item[on]]=item,dict
),{});
return list1.map(n => ({...n,...dict[n[on]]}
))};
Очевидно, что приведенные выше примеры довольно просты (объединение двух списков, каждый из которых имеет длину 3).Есть более сложные случаи, с которыми я работаю.
Я не знаю, есть ли какие-нибудь более умные (и идеально функциональные) методы, которые я должен использовать.