我有一个像这样的数据对象:
{
"data1": [
[
"ID",
"name",
"Birthday"
],
[
"10",
"thomas",
"1992-03-17"
],
[
"11",
"Emily",
"2000-03-03"
]
],
"data2": [
[
"Balance",
"ID"
],
[
"$4500",
"10"
],
[
"$1500",
"13"
]
]
}
它包含两个数组data1
和data2
。
每个数组的第一行是列的名称,其余行具有数据(像表一样考虑数据)。
我想比较两个数组中的ID
字段,如果ID
匹配,则最终输出将包含一列Balance
,其余额与该{{1} },如果ID
不匹配,则ID
将是Balance
。
预期输出:
$0
我发现要完成这个挑战。可以将其视为MySQL中的LEFT-JOIN。 我提到了此solution,但由于我没有响应中的键,因此在我的情况下不起作用。
编辑:我还需要加入其他字段。
答案 0 :(得分:2)
您可以使用Array.prototype.map(),find,filter,slice,reduce,concat,includes和{{ 3}}。
此解决方案:
Balance
中存在一个字段时,才附加一个data2
字段。data1
和data2
中没有数据,则使用默认值。
function merge({ data1, data2 }, defaults) {
// get the final headers, add/move 'Balance' to the end
const headers = [...data1[0].filter(x => x !== 'Balance')]
.concat(data2[0].includes('Balance') ? ['Balance'] : []);
// map the data from data1 to an array of objects, each key is the header name, also merge the default values.
const d1 = data1.slice(1)
.map(x => x.reduce((acc, y, i) => ({ ...defaults, ...acc, [data1[0][i]]: y }), {}));
// map the data from data2 to an array of objects, each key is the header name
const d2 = data2.slice(1)
.map(x => x.reduce((acc, y, i) => ({ ...acc, [data2[0][i]]: y }), {}));
// combine d1 and d2
const output = d1.map((x, i) => { // iterate over d1
// merge values from d2 into this value
const d = Object.assign(x, d2.find(y => y['ID'] === x['ID']));
// return an array ordered according to the header
return headers.map(h => d[h]);
});
return { output: [headers, ...output] };
}
const test0 = {
data1: [[ "ID","name","Birthday","other"],["10","thomas","1992-03-17","empty"],["11","Emily","2000-03-03","empty"]],
data2: [["other", "ID", "Balance", "city"],["hello", "10", "$4500", "New York"],["world", "10","$8","Brazil"]]
};
const test1 = {
data1: [["ID","name","Birthday"],["10","thomas","1992-03-17"],["11","Emily","2000-03-03"]],
data2: [["other","ID"],["x","10"],["y","11"]]
};
console.log(merge(test0, { Balance: '$0' }));
console.log(merge(test1, { Balance: '$0' }));
答案 1 :(得分:1)
const KEY_ID = "ID";
var data = {
"data1": [
[ "ID", "name", "Birthday" ],
[ "10", "thomas", "1992-03-17" ],
[ "11", "Emily", "2000-03-03" ]
],
"data2": [
[ "Balance", "ID" ],
[ "$4500", "10" ],
[ "$1500", "13" ]
]
}
var merged = Object.keys(data).map(function (key) {
var tmp = data[key].slice();
var heads = tmp.shift();
return tmp.map(function (item) {
var row = {};
heads.forEach(function (head, i) {
row[head] = item[i];
});
return row;
});
}).flat().reduce(function (acc, row) {
var found = acc.find(function (item) {
return row[KEY_ID] === item[KEY_ID];
})
if (!found) {
found = row;
acc.push(found);
} else {
Object.keys(row).forEach(function (head) {
found[head] = row[head];
});
}
return acc;
}, []);
console.log(merged);
此解决方案具有可伸缩性:如果添加属性,它将缩放新格式。
答案 2 :(得分:0)
您可以将所有表操作抽象为类:
function Table(array) {
const [head, ...values] = array;
const Entry =(entry) => ({
get(key) { return entry[ head.indexOf(key) ]; },
set(key, value) { entry[ head.indexOf(key) ] = value; }
});
return {
index(name) {
const result = {};
for(const value of values)
result[ value[ head.indexOf(name) ] ] = Entry(value);
return result;
},
*[Symbol.iterator]() {
for(const row of values)
yield Entry(row);
},
addRow(key) { head.push(key); }
};
}
可用作:
const users = Table(obj.data1);
const balances = Table(obj.data2);
const balanceByID = balance.index("ID");
users.addRow("Balance");
for(const user of users)
user.set("Balance", balanceByID[ user.get("ID") ].get("Balance"));
答案 3 :(得分:0)
let a = { "data1": [ ... ],"data2": [ ...] }
let r = a.data1.reduce((r,u,i)=>{
if(i !== 0)
{
let entry = a.data2.filter((a)=> a[1]===u[0])
r.push([...u,entry.length ? entry[0][0] : 0])
}
return r
},[[
"ID",
"name",
"Birthday",
"Balance"
]])