Как использовать Lodash для объединения двух коллекций на основе ключа?
У меня есть две коллекции, и у объектов есть общий ключ "userId". Как показано ниже:
var _= require('lodash');
var a = [
{ userId:"p1", item:1},
{ userId:"p2", item:2},
{ userId:"p3", item:4}
];
var b = [
{ userId:"p1", profile:1},
{ userId:"p2", profile:2}
];
Я хочу объединить их на основе "userId" для создания:
[ { userId: 'p1', item: 1, profile: 1 },
{ userId: 'p2', item: 2, profile:2 },
{ userId: 'p3', item: 4 } ]
У меня есть до сих пор:
var u = _.uniq(_.union(a, b), false, _.property('userId'));
Результат:
[ { userId: 'p1', item: 1 },
{ userId: 'p2', item: 2 },
{ userId: 'p3', item: 4 },
{ userId: 'p1', profile: 1 },
{ userId: 'p2', profile: 2 } ]
Как я могу слить их сейчас?
Я попробовал _.keyBy, но это приводит к:
{ p1: { userId: 'p1', profile: 1 },
p2: { userId: 'p2', profile: 2 },
p3: { userId: 'p3', item: 4 } }
что неверно.
Какой последний шаг я должен сделать?
Ответы
Ответ 1
Вы можете использовать _.map()
, _.assign()
и _.find()
.
// Iterate over first array of objects
_.map(a, function(obj) {
// add the properties from second array matching the userID
// to the object from first array and return the updated object
return _.assign(obj, _.find(b, {userId: obj.userId}));
});
Скриншот
var a = [{
userId: "p1",
item: 1
}, {
userId: "p2",
item: 2
}, {
userId: "p3",
item: 4
}];
var b = [{
userId: "p1",
profile: 1
}, {
userId: "p2",
profile: 2
}];
var arrResult = _.map(a, function(obj) {
return _.assign(obj, _.find(b, {
userId: obj.userId
}));
});
console.log(arrResult);
document.getElementById('result').innerHTML = JSON.stringify(arrResult, 0, 4);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.1.0/lodash.min.js"></script>
<pre id="result"></pre>
Ответ 2
Ответ с наибольшим количеством голосов не делает правильное слияние. Если второй массив содержит уникальное свойство, он не учитывается.
Этот подход делает правильное слияние.
Lodash
var a = [
{ userId:"p1", item:1},
{ userId:"p2", item:2},
{ userId:"p3", item:4}
];
var b = [
{ userId:"p1", profile:1},
{ userId:"p2", profile:2},
{ userId:"p4", profile:4}
];
var merged = _.merge(_.keyBy(a, 'userId'), _.keyBy(b, 'userId'));
var values = _.values(merged);
console.log(values);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Ответ 3
Только для полноты: предложение без какой-либо библиотеки.
function merge(a, b, key) {
function x(a) {
a.forEach(function (b) {
if (!(b[key] in obj)) {
obj[b[key]] = obj[b[key]] || {};
array.push(obj[b[key]]);
}
Object.keys(b).forEach(function (k) {
obj[b[key]][k] = b[k];
});
});
}
var array = [],
obj = {};
x(a);
x(b);
return array;
}
var a = [
{ userId: "p1", item: 1 },
{ userId: "p2", item: 2 },
{ userId: "p3", item: 4 }
],
b = [
{ userId: "p1", profile: 1 },
{ userId: "p2", profile: 2 }
],
c = merge(a, b, 'userId');
document.write('<pre>' + JSON.stringify(c, 0, 4) + '</pre>');
Ответ 4
Lodash имеет метод merge
, который работает с объектами (объекты с одним и тем же ключом объединяются). В этой демонстрации массивы a
и b
сначала преобразуются в объекты (где userId
- это ключ), затем объединяются, а результат преобразуется обратно в массив (_.values
) (избавление от ключей). _.flatten
тогда необходимо, потому что _.values
добавляет дополнительный уровень массива.
var u= _({}) // Start with an empty object
.merge(
_(a).groupBy("userId").value(),
_(b).groupBy("userId").value()
)
.values()
.flatten()
.value();
Ответ 5
Попробуйте демо
var a = [{
userId: "p1",
item: 1
}, {
userId: "p2",
item: 2
}, {
userId: "p3",
item: 4
}];
var b = [{
userId: "p1",
profile: 1
}, {
userId: "p2",
profile: 2
}];
a.forEach(function (aitem) {
b.forEach(function (bitem) {
if(aitem.userId === bitem.userId) {
_.assign(aitem, bitem);
}
});
});
console.log(a);
Ответ 6
ES6+ версия без lodash.
const array1 = [{ userId: "p1", item: 1 }, { userId: "p2", item: 2 },{ userId: "p3", item: 4 }];
const array2 = [{ userId: "p1", profile: 1 }, { userId: "p2", profile: 2 }];
const result = array1.map(a => ({
...a,
...array2.find(b => b.userId === a.userId) // _.find(array2, 'skuId') <-- or with lodash
}));
document.write('<pre>' + JSON.stringify(result, 0, 2) + '</pre>');
Ответ 7
Просто _.merge(a, b)
сделает эту работу. https://jsfiddle.net/8zw41drm/