合并重复的对象对象数组 [英] Merge duplicate objects in array of objects

查看:144
本文介绍了合并重复的对象对象数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面我有对象的数组,

  VAR数据= [
    {
        标签:第一册,
        数据:美国版
    },
    {
        标签:第一册,
        数据:英国版
    },
    {
        标签:第二册,
        数据:能版
    }
];

我要合并基础属性标签上的重复对象
使最终输出将看起来像下面,

  VAR数据= [
    {
        标签:第一册,
        数据:[美国版,英国版] // data属性合并
    },
    {
        标签:第二册,
        数据:能版
    }
];

有人可以帮我鉴定的方法呢?


解决方案

我可能会通过回路与过滤,保持地图的对象跟踪我看到之前,沿着这些线路的(编辑,以反映您的同意,是的,这是有道理的,以(输入)。数据总是一个数组)的:

  VAR看到= {};
数据= data.filter(功能(输入){
    VAR previous;    //我们以前见过这个标签?
    如果(seen.hasOwnProperty(entry.label)){
        //是的,抓住它,而这个数据添加到它
        previous =见过[entry.label]
        previous.data.push(entry.data);        //不要保留这个条目,我们已经把它合并到previous 1
        返回false;
    }    // entry.data可能不是一个数组;让一个一致性
    如果(!Array.isArray(entry.data)){
        entry.data = [entry.data];
    }    //记住,我们已经看到了它
    看到[entry.label] =条目;    //保留这一块,我们将合并到相匹配的是其他任何
    返回true;
});

在一个ES6的环境中,我会使用 =可见新地图(),而不是可见= {}

注意 Array.isArray 被定义ES5,所以像IE8的一些比较旧的浏览器将无法拥有它。它可以很容易地匀/ polyfilled,虽然:

 如果(!Array.isArray){
    Array.isArray =(函数(){
        VAR的toString = Object.prototype.toString;
        返回函数(){
            返回toString.call(一)===[对象数组];
        };
    })();
}

附注:我大概也始终 entry.data 一个数组,即使我没有看到两个它的价值观,因为一致的数据结构更容易对付。我没有这样做,因为上面你的最终结果表明: 数据仅仅是一个字符串时,只有一个匹配的条目。(我们所做的上面了。)

活生生的例子(ES5版):

\r
\r

VAR数据= [\r
    {\r
        标签:第一册,\r
        数据:美国版\r
    },\r
    {\r
        标签:第一册,\r
        数据:英国版\r
    },\r
    {\r
        标签:第二册,\r
        数据:能版\r
    }\r
];\r
snippet.log(之前:);\r
snippet.log(JSON.stringify(数据,空,2),pre);\r
变种看出= {};\r
数据= data.filter(功能(输入){\r
    VAR previous;\r
\r
    //我们以前见过这个标签?\r
    如果(seen.hasOwnProperty(entry.label)){\r
        //是的,抓住它,而这个数据添加到它\r
        previous =见过[entry.label]\r
        previous.data.push(entry.data);\r
\r
        //不要保留这个条目,我们已经把它合并到previous 1\r
        返回false;\r
    }\r
\r
    // entry.data可能不是一个数组;让一个一致性\r
    如果(!Array.isArray(entry.data)){\r
        entry.data = [entry.data];\r
    }\r
\r
    //记住,我们已经看到了它\r
    看到[entry.label] =条目;\r
\r
    //保留这一块,我们将合并到相匹配的是其他任何\r
    返回true;\r
});\r
snippet.log(后);\r
snippet.log(JSON.stringify(数据,空,2),pre);

\r

< - 脚本提供了`snippet`对象,请参见http:/ /meta.stackexchange.com/a/242144/134069 - >\r
<脚本SRC =htt​​p://tjcrowder.github.io/simple-snippets-console/snippet.js>< / SCRIPT>

\r

\r
\r

I have below array of objects,

var data = [
    {
        label: "Book1",
        data: "US edition"
    },
    {
        label: "Book1",
        data: "UK edition"
    },
    {
        label: "Book2",
        data: "CAN edition"
    }
];

I want to merge the duplicate objects based on attribute 'label' so that Final output will look like below,

var data = [
    {
        label: "Book1",
        data: ["US edition", "UK edition"] //data attribute is merged
    },
    {
        label: "Book2",
        data: "CAN edition"
    }
];

Can someone help me identify the approach?

解决方案

I would probably loop through with filter, keeping track of a map of objects I'd seen before, along these lines (edited to reflect your agreeing that yes, it makes sense to make (entry).data always an array):

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

In an ES6 environment, I'd use seen = new Map() rather than seen = {}.

Note: Array.isArray was defined by ES5, so some quite older browsers like IE8 won't have it. It can easily be shimmed/polyfilled, though:

if (!Array.isArray) {
    Array.isArray = (function() {
        var toString = Object.prototype.toString;
        return function(a) {
            return toString.call(a) === "[object Array]";
        };
    })();
}

Side note: I'd probably also always make entry.data an array, even if I didn't see two values for it, because consistent data structures are easier to deal with. I didn't do that above because your end result showed data being just a string when there was only one matching entry. (We've done that above now.)

Live example (ES5 version):

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>

这篇关于合并重复的对象对象数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆