我有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有一个优化版本,我想使用它。
使用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");
Linq.js http://linqjs.codeplex.com/将与许多其他事情一起加入
不,LoDash没有加入它的prety易于实现你自己,虽然,这不是一个连接,但选择所有人匹配的汽车:
var peopleWithCars = _.filter(people, function (person) {
return _.exists(cars, function(car) {
return car.id === person.id;
});
});
您可以使用Alasql JavaScript SQL库来连接两个或多个对象数组:
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]);
试试这个例子at jsFiddle。
这是一个简单的循环,我为Javascript(在本例中为JQuery)在someID上“加入”obj1和obj2,并将一个属性从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'));
结果
[
{
"leftId": 4,
"name": "Will"
},
{
"leftId": 3,
"name": "Michael"
},
{
"leftId": 8,
"name": "Susan",
"rightId": 8,
"color": "Red"
},
{
"leftId": 2,
"name": "Bob",
"rightId": 2,
"color": "Orange"
}
]
你可以用普通的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
})
);
};