Ответ 1
Взгляните на это: шесть реализаций соединения в javascript.
У меня есть 2 списка объектов:
people =
[{id: 1, name: "Tom", carid: 1},
{id: 2, name: "Bob", carid: 1},
{id: 3, name: "Sir Benjamin Rogan-Josh IV", carid: 2}];
cars=
[{id: 1, name: "Ford Fiesta", color: "blue"},
{id: 2, name: "Ferrari", color: "red"},
{id: 3, name: "Rover 25", color: "Sunset Melting Yellow with hints of yellow"}];
Есть ли функция (возможно, в Angular, JQuery, Underscore, LoDash или другая внешняя библиотека), чтобы сделать левое соединение в одной строке? Что-то вроде:
peoplewithcars = leftjoin( people, cars, "carid", "id");
Я могу написать свой, но если у LoDash есть оптимизированная версия, я бы хотел использовать это.
Взгляните на это: шесть реализаций соединения в javascript.
Linq.js http://linqjs.codeplex.com/ будет делать соединения вместе со многими другими вещами
Нетрудно реализовать, используя underscore.js
function leftJoin(left, right, left_id, right_id) {
var result = [];
_.each(left, function (litem) {
var f = _.filter(right, function (ritem) {
return ritem[right_id] == litem[left_id];
});
if (f.length == 0) {
f = [{}];
}
_.each(f, function (i) {
var newObj = {};
_.each(litem, function (v, k) {
newObj[k + "1"] = v;
});
_.each(i, function (v, k) {
newObj[k + "2"] = v;
});
result.push(newObj);
});
});
return result;
}
leftJoin(people, cars, "carid", "id");
Нет, у LoDash нет присоединения, это претит легко реализовать свое, хотя это не совсем объединение, но выбирает всех людей с подходящим автомобилем:
var peopleWithCars = _.filter(people, function (person) {
return _.exists(cars, function(car) {
return car.id === person.id;
});
});
Вы можете использовать Alasql JavaScript-библиотека JavaScript для объединения двух или более массивов объектов:
var res = alasql('SELECT people.name AS person_name, cars.name, cars.color \
FROM ? people LEFT JOIN ? cars ON people.carid = cars.id',[people, cars]);
Попробуйте этот пример в jsFiddle.
Вот простой цикл, который я сделал для Javascript (в этом случае JQuery) для "объединения" obj1 и obj2 на someID и добавления одного свойства из obj2 в obj1.
Если вы хотите сделать более полное соединение, вы можете пройти и расширить его до цикла на obj2.hasOwnProperty() и скопировать его также.
$.each(obj1,function(i){
$.each(obj2, function(k){
if (obj2[k].someID == obj1[i].someID ){
obj1[i].someValue = obj2[k].someValue;
}
});
});
В этом примере используется Lodash, чтобы присоединиться к первому совпадающему объекту. Не совсем то, что задает вопрос, но я нашел полезный ответ.
var leftTable = [{
leftId: 4,
name: 'Will'
}, {
leftId: 3,
name: 'Michael'
}, {
leftId: 8,
name: 'Susan'
}, {
leftId: 2,
name: 'Bob'
}];
var rightTable = [{
rightId: 1,
color: 'Blue'
}, {
rightId: 8,
color: 'Red'
}, {
rightId: 2,
color: 'Orange'
}, {
rightId: 7,
color: 'Red'
}];
console.clear();
function leftJoinSingle(leftTable, rightTable, leftId, rightId) {
var joinResults = [];
_.forEach(leftTable, function(left) {
var findBy = {};
findBy[rightId] = left[leftId];
var right = _.find(rightTable, findBy),
result = _.merge(left, right);
joinResults.push(result);
})
return joinResults;
}
var joinedArray = leftJoinSingle(leftTable, rightTable, 'leftId', 'rightId');
console.log(JSON.stringify(joinedArray, null, '\t'));
Вы можете делать такие вещи в простом javascript.
people.map(man =>
cars.some(car => car.id === man.carid) ?
cars.filter(car => car.id === man.carid).map(car => ({car, man})) :
{man}
).reduce((a,b)=> a.concat(b),[]);
В этой реализации используется оператор распространения ES6. Опять же, не библиотечная функция, как просили.
const leftJoin = (objArr1, objArr2, key1, key2) => {
return objArr1.map(
anObj1 => ({
...objArr2.find(
anObj2 => anObj1[key1] === anObj2[key2]
),
...anObj1
})
);
};