我有以下对象数组,
var data = [
{
label: "Book1",
data: "US edition"
},
{
label: "Book1",
data: "UK edition"
},
{
label: "Book2",
data: "CAN edition"
}
];
我想根据属性'label'合并重复的对象 所以最终输出将如下所示,
var data = [
{
label: "Book1",
data: ["US edition", "UK edition"] //data attribute is merged
},
{
label: "Book2",
data: "CAN edition"
}
];
有人可以帮我确定方法吗?
答案 0 :(得分:16)
我可能会使用filter
进行循环,跟踪我之前看到的对象地图,沿着这些行(编辑以反映您同意是的,有意义的是(entry).data
始终是一个数组):
var seen = {};
data = data.filter(function(entry) {
var previous;
// Have we seen this label before?
if (seen.hasOwnProperty(entry.label)) {
// Yes, grab it and add this data to it
previous = seen[entry.label];
previous.data.push(entry.data);
// Don't keep this entry, we've merged it into the previous one
return false;
}
// entry.data probably isn't an array; make it one for consistency
if (!Array.isArray(entry.data)) {
entry.data = [entry.data];
}
// Remember that we've seen it
seen[entry.label] = entry;
// Keep this one, we'll merge any others that match into it
return true;
});
在ES6环境中,我使用seen = new Map()
而不是seen = {}
。
注意:Array.isArray
是由ES5定义的,因此像IE8这样的一些相当老的浏览器都没有。它可以很容易地进行填充/填充,但是:
if (!Array.isArray) {
Array.isArray = (function() {
var toString = Object.prototype.toString;
return function(a) {
return toString.call(a) === "[object Array]";
};
})();
}
旁注:即使我没有看到两个值,我也可能始终使 (我们现在已经完成了这个。) entry.data
成为数组,因为数据一致结构更容易处理。我上面没有这样做,因为当只有一个匹配的条目时,你的最终结果显示data
只是一个字符串。
实例(ES5版):
var data = [
{
label: "Book1",
data: "US edition"
},
{
label: "Book1",
data: "UK edition"
},
{
label: "Book2",
data: "CAN edition"
}
];
snippet.log("Before:");
snippet.log(JSON.stringify(data, null, 2), "pre");
var seen = {};
data = data.filter(function(entry) {
var previous;
// Have we seen this label before?
if (seen.hasOwnProperty(entry.label)) {
// Yes, grab it and add this data to it
previous = seen[entry.label];
previous.data.push(entry.data);
// Don't keep this entry, we've merged it into the previous one
return false;
}
// entry.data probably isn't an array; make it one for consistency
if (!Array.isArray(entry.data)) {
entry.data = [entry.data];
}
// Remember that we've seen it
seen[entry.label] = entry;
// Keep this one, we'll merge any others that match into it
return true;
});
snippet.log("After:");
snippet.log(JSON.stringify(data, null, 2), "pre");

<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
答案 1 :(得分:3)
尝试使用以下方法,它可以找到并且很短
var data = [
{
label: "Book1",
data: "US edition"
},
{
label: "Book1",
data: "UK edition"
},
{
label: "Book2",
data: "CAN edition"
}
];
const result = Array.from(new Set(data.map(s => s.label)))
.map(lab => {
return {
label: lab,
data: data.filter(s => s.label === lab).map(edition => edition.data)
}
})
console.log(result);
答案 2 :(得分:0)
此代码在最新版本的Firefox上测试。要在其他浏览器上工作,请将库的Array.isArray更改为lodash或您喜欢的任何内容。
var data = [
{
label: "Book1",
data: "US edition"
},
{
label: "Book1",
data: "UK edition"
},
{
label: "Book2",
data: "CAN edition"
}
],
i = 0,
j = data.length - 1,
current;
for (;i < data.length; i++) {
current = data[i];
for (;j > i; j--) {
if (current.label === data[j].label) {
if (Array.isArray(current.data)) {
current.data = current.data.concat([data[j].data]);
} else {
current.data = [].concat([data[j].data, current.data]);
}
data.splice(j, 1);
}
}
}
console.log(data);
答案 3 :(得分:0)
我遇到了同样的情况,我希望在这里使用Set
代替我的
const data = [
{
label: "Book1",
data: "US edition"
},
{
label: "Book1",
data: "UK edition"
},
{
label: "Book2",
data: "CAN edition"
},
{
label: "Book3",
data: "CAN edition"
},
{
label: "Book3",
data: "CANII edition"
}
];
const filteredArr = data.reduce((acc, current) => {
const x = acc.find(item => item.label === current.label);
if (!x) {
const newCurr = {
label: current.label,
data: [current.data]
}
return acc.concat([newCurr]);
} else {
const currData = x.data.filter(d => d === current.data);
if (!currData.length) {
const newData = x.data.push(current.data);
const newCurr = {
label: current.label,
data: newData
}
return acc;
} else {
return acc;
}
}
}, []);
console.log(filteredArr);
答案 4 :(得分:0)
var data = [
{
label: "Book1",
data: "US edition"
},
{
label: "Book1",
data: "UK edition"
},
{
label: "Book2",
data: "CAN edition"
}
].filter(function(e, index ,b) {
k = b.map(z => z.label)
if(k.includes(e.label, index+1)){
indexPosition = k.indexOf(e.label, index+1);
b[indexPosition].data = (e.data+"||"+b[indexPosition].data);
}else{
e.data = e.data.split("||").length > 1 ? e.data.split("||") : e.data;
return e;
}
});
console.log(data)