我有一个对象数组(来自XLSX.js解析器,所以它的长度和内容各不相同),表示已经给予项目的资助。
简化后,它看起来像这样:
var grants = [
{ id: "p_1", location: "loc_1", type: "A", funds: "5000" },
{ id: "p_2", location: "loc_2", type: "B", funds: "2000" },
{ id: "p_3", location: "loc_3", type: "C", funds: "500" },
{ id: "p_2", location: "_ibid", type: "D", funds: "1000" },
{ id: "p_2", location: "_ibid", type: "E", funds: "3000" }
];
我需要将这些合并成一个新的数组,看起来像这样:
var projects = [
{ id: "p_1", location: "loc_1", type: "A", funds: "5000" },
{ id: "p_2", location: "loc_2", type: ["B", "D", "E"], funds: ["2000", "1000", "3000"] },
{ id: "p_3", location: "loc_3", type: "C", funds: "500" }
];
…因此,当id
相同时,它将合并对象并将中的一些键值(在示例中为type
和funds
)组合成一个简单的子数组。这些合并对象中的其他键(location
)继承第一个实例的值,而忽略其余的。
经过几次失败的尝试和大量的在线搜索,我从这个答案中得到了一个想法,通过grants
像这样循环:
var res = {};
$.each(grants, function (key, value) {
if (!res[value.id]) {
res[value.id] = value;
} else {
res[value.id].type = [res[value.id].type, value.type];
res[value.id].funds = [res[value.id].funds, value.funds];
}
});
var projects = []
projects = $.map( res, function (value) { return value; } );
它实际上工作完美,除了我需要一个数组,我从两端(从上面提到的答案)删除了.join(',')
,这反过来又产生了我现在似乎无法解决的问题。如果子数组中至少有三个元素,那么子数组会以某种方式相互嵌套在中!我有点理解为什么(循环),但我想知道是否有一种方法将对象内的所有这些小多维数组转换为单个数组(如:type: ["B", "D", "E"]
)?
var grants = [
{ id: "p_1", location: "loc_1", type: "A", funds: "5000" },
{ id: "p_2", location: "loc_2", type: "B", funds: "2000" },
{ id: "p_3", location: "loc_3", type: "C", funds: "500" },
{ id: "p_2", location: "_ibid", type: "D", funds: "1000" },
{ id: "p_2", location: "_ibid", type: "E", funds: "3000" }
];
var res = {};
$.each(grants, function (key, value) {
if (!res[value.id]) {
res[value.id] = value;
} else {
res[value.id].type = [res[value.id].type, value.type];
res[value.id].funds = [res[value.id].funds, value.funds];
}
});
var projects = []
projects = $.map( res, function (value) { return value; } );
$("pre").html(JSON.stringify(projects,null,2));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="json"></pre>
这是个好主意吗?
var grants = [
{ id: "p_1", location: "loc_1", type: "A", funds: "5000" },
{ id: "p_2", location: "loc_2", type: "B", funds: "2000" },
{ id: "p_3", location: "loc_3", type: "C", funds: "500" },
{ id: "p_2", location: "_ibid", type: "D", funds: "1000" },
{ id: "p_2", location: "_ibid", type: "E", funds: "3000" }
];
var joined = [];
// map and push to joined
grants.map(
function (v) {
if (!(v.id in this)) {
this[v.id] = v;
joined.push(v);
} else {
var current = this[v.id];
current.type = [v.type].concat(current.type);
current.funds = [v.funds].concat(current.funds);
}
}, {}
);
// show it
document.querySelector('#result').textContent =
JSON.stringify(joined, null, ' ');
<pre id="result"></pre>
你可以改变这些行:
res[value.id].type = [res[value.id].type, value.type];
res[value.id].funds = [res[value.id].funds, value.funds];
:
Array.isArray(res[value.id].type) ? res[value.id].type.push(value.type) : res[value.id].type = [res[value.id].type, value.type];
Array.isArray(res[value.id].funds) ? res[value.id].funds.push(value.funds) : res[value.id].funds = [res[value.id].funds, value.funds];
这样做:
var tempArr = [];
var result = [];
for(i in grants){
var rowObj = grants[i];
var idPos = tempArr.indexOf(rowObj.id);
if(idPos > -1){
result[idPos].type.push(rowObj.type);
result[idPos].funds.push(rowObj.funds);
}else{
tempArr.push(rowObj.id);
rowObj.type = [rowObj.type]
rowObj.funds = [rowObj.funds]
result.push(rowObj);
}
}
console.log(result);
我提出这个解决方案。
它的特点是查找,如果索引存在于项目数组中,则push type和funds;如果不存在,则type和funds属性更改为数组,并将值作为第一个元素。
var grants = [
{ id: "p_1", location: "loc_1", type: "A", funds: "5000" },
{ id: "p_2", location: "loc_2", type: "B", funds: "2000" },
{ id: "p_3", location: "loc_3", type: "C", funds: "500" },
{ id: "p_2", location: "_ibid", type: "D", funds: "1000" },
{ id: "p_2", location: "_ibid", type: "E", funds: "3000" }
],
project = [];
grants.forEach(function (a) {
!project.some(function (b, i) {
if (a.id === b.id) {
project[i].type.push(a.type);
project[i].funds.push(a.funds);
return true;
}
}) && project.push({ id: a.id, location: a.location, type: [a.type], funds: [a.funds] });
});
document.write('<pre>' + JSON.stringify(project, 0, 4) + '</pre>');