在我的AngularJS 1.3项目中,我尝试使用给定的键连接对象并进行合并。考虑下面的对象(为了更好地理解,将键考虑为表列):
var json = {
"filteredTask": [{
"Email_1202_1_1554368387884": "c@c",
"Number_1202_2_1554368395451": "50000",
"Number_1202_3_1554368408148": "30000",
"Text_Field_1202_4_1554368416611": "Developer"
}, {
"Email_1202_1_1554368387884": "b@b",
"Number_1202_2_1554368395451": "25000",
"Number_1202_3_1554368408148": "20000",
"Text_Field_1202_4_1554368416611": "QA"
}, {
"Email_1202_1_1554368387884": "a@a",
"Number_1202_2_1554368395451": "22000",
"Number_1202_3_1554368408148": "20000",
"Text_Field_1202_4_1554368416611": "Developer"
}, {
"Text_Field_1202_1_1554367796776": "c@c",
"Text_Field_1202_2_1554367980023": "Admin",
"Text_Field_1202_3_1554367980751": "HR"
}, {
"Text_Field_1202_1_1554367796776": "b@b",
"Text_Field_1202_2_1554367980023": "Non Technical",
"Text_Field_1202_3_1554367980751": "QA"
}, {
"Text_Field_1202_1_1554367796776": "a@a",
"Text_Field_1202_2_1554367980023": "Technical",
"Text_Field_1202_3_1554367980751": "Developer"
}],
"filter": {
"joinField": [{
"formField": {
"new_key": "Text_Field_1202_1_1554367796776"
},
"withFormField": {
"new_key": "Email_1202_1_1554368387884"
}
}, {
"formField": {
"new_key": "Text_Field_1202_3_1554367980751"
},
"withFormField": {
"new_key": "Text_Field_1202_4_1554368416611"
}
}]
}
};
请注意,filteredTask
包含所有数据,filter
包含联接字段关键字信息。
现在,我想像在JSON上执行SQL一样执行联接。例如,加入两个键Text_Field_1202_1_1554367796776
和Email_1202_1_1554368387884
(电子邮件匹配,例如a @ a,b @ b和c @ c),结果应如下所示。
[{
"Email_1202_1_1554368387884": "c@c",
"Number_1202_2_1554368395451": "50000",
"Number_1202_3_1554368408148": "30000",
"Text_Field_1202_4_1554368416611": "Developer",
"Text_Field_1202_1_1554367796776": "c@c",
"Text_Field_1202_2_1554367980023": "Admin",
"Text_Field_1202_3_1554367980751": "HR"
}, {
"Email_1202_1_1554368387884": "b@b",
"Number_1202_2_1554368395451": "25000",
"Number_1202_3_1554368408148": "20000",
"Text_Field_1202_4_1554368416611": "QA",
"Text_Field_1202_1_1554367796776": "b@b",
"Text_Field_1202_2_1554367980023": "Non Technical",
"Text_Field_1202_3_1554367980751": "QA"
}, {
"Email_1202_1_1554368387884": "a@a",
"Number_1202_2_1554368395451": "22000",
"Number_1202_3_1554368408148": "20000",
"Text_Field_1202_4_1554368416611": "Developer",
"Text_Field_1202_1_1554367796776": "a@a",
"Text_Field_1202_2_1554367980023": "Technical",
"Text_Field_1202_3_1554367980751": "Developer"
}]
现在,如果我用Text_Field_1202_1_1554367796776
(电子邮件)和Email_1202_1_1554368387884
(用Text_Field_1202_3_1554367980751
(指定))执行两次联接,例如Text_Field_1202_4_1554368416611
,那么考虑到电子邮件和名称都匹配:
[{
"Email_1202_1_1554368387884": "b@b",
"Number_1202_2_1554368395451": "25000",
"Number_1202_3_1554368408148": "20000",
"Text_Field_1202_4_1554368416611": "QA",
"Text_Field_1202_1_1554367796776": "b@b",
"Text_Field_1202_2_1554367980023": "Non Technical",
"Text_Field_1202_3_1554367980751": "QA"
}, {
"Email_1202_1_1554368387884": "a@a",
"Number_1202_2_1554368395451": "22000",
"Number_1202_3_1554368408148": "20000",
"Text_Field_1202_4_1554368416611": "Developer",
"Text_Field_1202_1_1554367796776": "a@a",
"Text_Field_1202_2_1554367980023": "Technical",
"Text_Field_1202_3_1554367980751": "Developer"
}]
我为此尝试了lodash library实用工具。
angular.forEach(json.filter.joinField, function (jField) {
var obj1 = _.filter(json.filteredTask, function (o1) {
return o1[jField.formField.new_key];
});
var obj2 = _.filter(json.filteredTask, function (o2) {
return o2[jField.withFormField.new_key];
});
// for intersaction data
var result = _.intersectionWith(_.cloneDeep(obj1), obj2, function (x, y) {
//Improvement needed here: when I print, it shows different keys and values and generated output differently.
return x[jField.formField.new_key] === y[jField.withFormField.new_key] && _.assign(x, y);
});
json.filteredTask = result;
});
console.log(json);
让我知道我们是否可以通过其他任何方式实现这一目标,或者可以改进这一方法。
答案 0 :(得分:2)
以下是您可以采取的步骤:
您可以在ES2018中做到这一点:
function join(obj) {
// Extract join conditions
const keys = obj.filter.joinField.map(pair =>
[pair.withFormField.new_key, pair.formField.new_key]);
const grouped = [new Map, new Map]; // groups for left & right side
const result = [];
// Put rows in buckets based on their join fields
for (const row of obj.filteredTask) {
// Determine which "side" of the join this row is on
let side = +(keys[0][1] in row);
// Create single key value:
let key = JSON.stringify(keys.map(pair => row[pair[side]]));
if (!grouped[side].has(key)) grouped[side].set(key, []);
grouped[side].get(key).push(row);
}
// Perform the join
for (const [key, rows1] of grouped[0]) {
// pick up rows from the other side that share the same key (intersection)
const rows2 = grouped[1].get(key);
if (!rows2) continue;
for (const row1 of rows1) {
for (const row2 of rows2) result.push({...row1, ...row2});
}
}
return result;
}
var data = {"filteredTask": [{"Email_1202_1_1554368387884": "c@c","Number_1202_2_1554368395451": "50000","Number_1202_3_1554368408148": "30000","Text_Field_1202_4_1554368416611": "Developer"}, {"Email_1202_1_1554368387884": "b@b","Number_1202_2_1554368395451": "25000","Number_1202_3_1554368408148": "20000","Text_Field_1202_4_1554368416611": "QA"}, {"Email_1202_1_1554368387884": "a@a","Number_1202_2_1554368395451": "22000","Number_1202_3_1554368408148": "20000","Text_Field_1202_4_1554368416611": "Developer"}, {"Text_Field_1202_1_1554367796776": "c@c","Text_Field_1202_2_1554367980023": "Admin","Text_Field_1202_3_1554367980751": "HR"}, {"Text_Field_1202_1_1554367796776": "b@b","Text_Field_1202_2_1554367980023": "Non Technical","Text_Field_1202_3_1554367980751": "QA"}, {"Text_Field_1202_1_1554367796776": "a@a","Text_Field_1202_2_1554367980023": "Technical","Text_Field_1202_3_1554367980751": "Developer"}],"filter": {"joinField": [{"formField": {"new_key": "Text_Field_1202_1_1554367796776"},"withFormField": {"new_key": "Email_1202_1_1554368387884"}}, {"formField": {"new_key": "Text_Field_1202_3_1554367980751"},"withFormField": {"new_key": "Text_Field_1202_4_1554368416611"}}]}};
const result = join(data);
console.log(result);
在ES5中:
function join(obj) {
// Extract join conditions
var keys = obj.filter.joinField.map(pair =>
[pair.withFormField.new_key, pair.formField.new_key]);
var grouped = [{}, {}]; // groups for left & right side
var result = [];
// Put rows in buckets based on their join fields
obj.filteredTask.forEach(function (row) {
// Determine which "side" of the join this row is on
var side = +(keys[0][1] in row);
// Create single key value:
var key = JSON.stringify(keys.map(function (pair) {
return row[pair[side]];
}));
if (!grouped[side][key]) grouped[side][key] = [];
grouped[side][key].push(row);
});
// Perform the join
for (var key in grouped[0]) {
var rows1 = grouped[0][key];
// pick up rows from the other side that share the same key (intersection)
var rows2 = grouped[1][key];
if (!rows2) continue;
rows1.forEach(function (row1) {
rows2.forEach(function (row2) {
result.push(Object.assign({}, row1, row2));
});
});
}
return result;
}
var data = {"filteredTask": [{"Email_1202_1_1554368387884": "c@c","Number_1202_2_1554368395451": "50000","Number_1202_3_1554368408148": "30000","Text_Field_1202_4_1554368416611": "Developer"}, {"Email_1202_1_1554368387884": "b@b","Number_1202_2_1554368395451": "25000","Number_1202_3_1554368408148": "20000","Text_Field_1202_4_1554368416611": "QA"}, {"Email_1202_1_1554368387884": "a@a","Number_1202_2_1554368395451": "22000","Number_1202_3_1554368408148": "20000","Text_Field_1202_4_1554368416611": "Developer"}, {"Text_Field_1202_1_1554367796776": "c@c","Text_Field_1202_2_1554367980023": "Admin","Text_Field_1202_3_1554367980751": "HR"}, {"Text_Field_1202_1_1554367796776": "b@b","Text_Field_1202_2_1554367980023": "Non Technical","Text_Field_1202_3_1554367980751": "QA"}, {"Text_Field_1202_1_1554367796776": "a@a","Text_Field_1202_2_1554367980023": "Technical","Text_Field_1202_3_1554367980751": "Developer"}],"filter": {"joinField": [{"formField": {"new_key": "Text_Field_1202_1_1554367796776"},"withFormField": {"new_key": "Email_1202_1_1554368387884"}}, {"formField": {"new_key": "Text_Field_1202_3_1554367980751"},"withFormField": {"new_key": "Text_Field_1202_4_1554368416611"}}]}};
var result = join(data);
console.log(result);