Javascript 在对象数组中合并重复对象

Javascript 在对象数组中合并重复对象,javascript,arrays,Javascript,Arrays,下面是一组对象 var data = [ { label: "Book1", data: "US edition" }, { label: "Book1", data: "UK edition" }, { label: "Book2", data: "CAN edition" } ]; 我想根据属性“label”合并重复的对象 最终的输出如下所示 va

下面是一组对象

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"
    }
];

有人能帮我确定方法吗?

我可能会循环使用
过滤器
,沿着这些线跟踪我以前见过的对象的地图(编辑以反映您同意是的,制作
(条目)是有意义的。数据始终是一个数组):

在ES6环境中,我会使用
seen=newmap()
而不是
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]";
        };
    })();
}
旁注:我可能也会总是输入
数据。数据
是一个数组,即使我没有看到它的两个值,因为一致的数据结构更容易处理。我没有在上面这样做,因为您的最终结果显示,
数据
只是一个字符串,而只有一个匹配条目。(我们现在已经完成了上述操作。)

实时示例(ES5版本):

var数据=[
{
标签:“Book1”,
数据:“美国版”
},
{
标签:“Book1”,
数据:“英国版”
},
{
标签:“Book2”,
数据:“CAN版本”
}
];
log(“之前:”);
log(JSON.stringify(data,null,2),“pre”);
var-seen={};
data=data.filter(函数(条目){
var-previous;
//我们以前见过这个标签吗?
if(参见.hasOwnProperty(entry.label)){
//是的,抓住它并将这些数据添加到其中
previous=已看到[entry.label];
上一个.data.push(entry.data);
//不要保留此条目,我们已将其合并到上一个条目中
返回false;
}
//entry.data可能不是数组;为保持一致性,请将其设置为数组
if(!Array.isArray(entry.data)){
entry.data=[entry.data];
}
//记住我们已经看过了
seen[entry.label]=条目;
//保留这一个,我们将合并任何其他匹配到它
返回true;
});
log(“之后:”);
log(JSON.stringify(data,null,2),“pre”)

此代码在最新版本的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);
var数据=[
{
标签:“Book1”,
数据:“美国版”
},
{
标签:“Book1”,
数据:“英国版”
},
{
标签:“Book2”,
数据:“CAN版本”
}
],
i=0,
j=数据长度-1,
现在的
对于(;ii;j--){
if(current.label==数据[j].label){
if(Array.isArray(current.data)){
current.data=current.data.concat([data[j].data]);
}否则{
current.data=[].concat([data[j].data,current.data]);
}
数据拼接(j,1);
}
}
} 
控制台日志(数据);

我遇到了同样的情况,我希望在这里使用
集合
而不是我的

const数据=[
{
标签:“Book1”,
数据:“美国版”
},
{
标签:“Book1”,
数据:“英国版”
},
{
标签:“Book2”,
数据:“CAN版本”
},
{
标签:“Book3”,
数据:“CAN版本”
},
{
标签:“Book3”,
数据:“CANII版”
}
];
const filteredar=数据减少((acc,当前)=>{
const x=acc.find(item=>item.label==current.label);
如果(!x){
常数newCurr={
标签:current.label,
数据:[当前数据]
}
返回acc.concat([newCurr]);
}否则{
const currData=x.data.filter(d=>d==current.data);
如果(!currData.length){
const newData=x.data.push(当前数据);
常数newCurr={
标签:current.label,
数据:新数据
}
返回acc;
}否则{
返回acc;
}
}
}, []);
控制台日志(Filteredar)
var数据=[
{
标签:“Book1”,
数据:“美国版”
},
{
标签:“Book1”,
数据:“英国版”
},
{
标签:“Book2”,
数据:“CAN版本”
}
].过滤器(功能(e、索引、b){
k=b.map(z=>z.label)
if(k.包括(如标签、索引+1)){
indexPosition=k.indexOf(e.标签,索引+1);
b[indexPosition].data=(e.data+“| |”+b[indexPosition].data);
}否则{
e、 data=e.data.split(“| |”)。长度>1?e.data.split(“| |”):e.data;
返回e;
}
});

console.log(data)
尝试下面的方法,它很有效而且很短

 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);

在我的例子中,
new Set(array1,array2)
工作得非常完美。多么优化和卓越的逻辑:)数据如何为重复的数组获取更新的数组?@finbarmagin:我不理解这个问题。我不明白合并的数组是如何分配给具有相同标签的返回数组项的。我还想知道这整件事是否可以用映射和Reduce重写?@FinbarMaginn:
entry.data=[entry.data]
previous=seed[entry.label];上一个.data.push(entry.data)是什么做的。重新映射/减少:可能。不过,在上面的简单循环中不需要复杂度。
 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);