首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从JSON数组中删除重复的对象

从JSON数组中删除重复的对象
EN

Stack Overflow用户
提问于 2014-05-07 10:47:12
回答 17查看 122.9K关注 0票数 41

我有一个看起来像这样的数组:

代码语言:javascript
复制
var standardsList = [
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Geometry"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Orders of Operation"},
    {"Grade": "Math 2", "Domain": "Geometry"},
    {"Grade": "Math 2", "Domain": "Geometry"}
];

我需要删除重复项,这样就可以保留下面这样的内容:

代码语言:javascript
复制
var standardsList = [
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Geometry"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Orders of Operation"},
    {"Grade": "Math 2", "Domain": "Geometry"}
];

我尝试过安装underscore.js和使用._uniq,但似乎只有在对象中出现单个key:value对时才有效。我似乎不能让它在多个键上工作。

当我尝试这样的事情时:

代码语言:javascript
复制
var uniqueStandards = _.uniq(standardsList, function(item, key, Domain){
    return item.Domain;
});

我只得到前三个唯一的值(每个年级一个)。但我需要跨年级和领域的所有唯一值。有没有一种简单的方法将两个键都提供给_.uniq函数?

最终,我需要一个列表,将每个唯一的等级作为标题,将唯一的域作为列表项传递到HTML页面。我可能做错了,所以如果有更简单的方法来实现最终目标,我对想法持开放态度。

提前感谢!

编辑:得到了一些很好的回应,并想澄清我的最终目标是什么。我正在尝试用HTML创建表单的一系列列表:

代码语言:javascript
复制
<div>
    <h3>Math K</h3>
    <li>Counting & Cardinality</li>
    <li>Geometry</li>
</div>
<div>
    <h3>Math 1</h3>
    <li>Counting & Cardinality</li>
    <li>Orders of Operation</li>
</div>
<div>
    <h3>Math 2</h3>
    <li>Geometry</li>
</div>

我最初的想法是创建一个数组,并使用$("#divid").append(array)将其推入页面上的<div>元素中

EN

回答 17

Stack Overflow用户

回答已采纳

发布于 2014-05-07 11:30:31

最终,我需要一个列表,每个唯一的等级作为标题和唯一的域作为列表项目,以传递到

页面。我可能做错了,所以如果有更简单的方法来实现最终目标,我对想法持开放态度。

因此,您实际上并不需要您所要求的格式的输出数组。

在这种情况下,我会用一个非常简单有效的解决方案直接切入正题:

代码语言:javascript
复制
var grades = {};
standardsList.forEach( function( item ) {
    var grade = grades[item.Grade] = grades[item.Grade] || {};
    grade[item.Domain] = true;
});

console.log( JSON.stringify( grades, null, 4 ) );

生成的grades对象为:

代码语言:javascript
复制
{
    "Math K": {
        "Counting & Cardinality": true,
        "Geometry": true
    },
    "Math 1": {
        "Counting & Cardinality": true,
        "Orders of Operation": true
    },
    "Math 2": {
        "Geometry": true
    }
}

关于这种方法的一个有趣的事情是它非常快。请注意,与其他需要多次传递的解决方案不同,它只对输入数组进行一次传递(无论是您自己编写还是由_.uniq()为您完成)。对于少数项目,这并不重要,但对于较大的列表,最好记住这一点。

有了这个对象,您现在就拥有了运行任何代码或生成任何其他所需格式所需的一切。例如,如果您确实需要您提到的确切的数组输出格式,则可以使用:

代码语言:javascript
复制
var outputList = [];
for( var grade in grades ) {
    for( var domain in grades[grade] ) {
        outputList.push({ Grade: grade, Domain: domain });
    }
}

JSON.stringify( outputList, null, 4 );

这将记录以下内容:

代码语言:javascript
复制
[
    {
        "Grade": "Math K",
        "Domain": "Counting & Cardinality"
    },
    {
        "Grade": "Math K",
        "Domain": "Geometry"
    },
    {
        "Grade": "Math 1",
        "Domain": "Counting & Cardinality"
    },
    {
        "Grade": "Math 1",
        "Domain": "Orders of Operation"
    },
    {
        "Grade": "Math 2",
        "Domain": "Geometry"
    }
]

Rai在评论中询问这行代码是如何工作的:

代码语言:javascript
复制
var grade = grades[item.Grade] = grades[item.Grade] || {};

这是一种常见的习惯用法,用于获取对象属性或在缺少属性时提供默认值。请注意,=分配是按从右到左的顺序完成的。因此我们可以从字面上将其转换为使用if语句和temp变量:

代码语言:javascript
复制
// Fetch grades[item.Grade] and save it in temp
var temp = grades[item.Grade];
if( ! temp ) {
    // It was missing, so use an empty object as the default value
    temp = {};
}
// Now save the result in grades[item.Grade] (in case it was missing)
// and in grade
grades[item.Grade] = temp;
var grade = temp;

您可能会注意到,在grades[item.Grade]已经存在的情况下,我们将获取刚刚获取的值并将其存储回相同的属性中。当然,这是不必要的,如果您像这样编写代码,您可能不会这样做。相反,您可以将其简化:

代码语言:javascript
复制
var grade = grades[item.Grade];
if( ! grade ) {
    grade = grades[item.Grade] = {};
}

这将是一种完全合理的方式来编写相同的代码,而且效率也更高。它还为您提供了一种比||习惯用法所依赖的“真实性”更具体的测试方法。例如,您可能希望使用if( grade === undefined )而不是if( ! grade )

票数 18
EN

Stack Overflow用户

发布于 2014-05-07 11:12:49

代码语言:javascript
复制
function arrUnique(arr) {
    var cleaned = [];
    arr.forEach(function(itm) {
        var unique = true;
        cleaned.forEach(function(itm2) {
            if (_.isEqual(itm, itm2)) unique = false;
        });
        if (unique)  cleaned.push(itm);
    });
    return cleaned;
}

var standardsList = arrUnique(standardsList);

这将返回

代码语言:javascript
复制
var standardsList = [
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Geometry"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Orders of Operation"},
    {"Grade": "Math 2", "Domain": "Geometry"}
];

这就是你想要的?

票数 28
EN

Stack Overflow用户

发布于 2017-11-16 01:06:39

我知道已经有很多答案了,但对于复杂的json结构,对我来说最好的答案是:

代码语言:javascript
复制
var arr = [{ "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCSW", "desc": "SOUTHWEST", "code": "RCSW", "level": 0, "save": "RCSW : SOUTHWEST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCSW", "desc": "SOUTHWEST", "code": "RCSW", "level": 0, "save": "RCSW : SOUTHWEST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RCSW", "desc": "SOUTHWEST", "code": "RCSW", "level": 0, "save": "RCSW : SOUTHWEST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RCNW", "desc": "MIDWEST", "code": "RCNW", "level": 0, "save": "RCNW : MIDWEST", "attribute1": "", "attribute2": "" }, { "State": "RCSW", "desc": "SOUTHWEST", "code": "RCSW", "level": 0, "save": "RCSW : SOUTHWEST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCNW", "desc": "MIDWEST", "code": "RCNW", "level": 0, "save": "RCNW : MIDWEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCNW", "desc": "MIDWEST", "code": "RCNW", "level": 0, "save": "RCNW : MIDWEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCNW", "desc": "MIDWEST", "code": "RCNW", "level": 0, "save": "RCNW : MIDWEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }];

var clean = arr.filter((arr, index, self) =>
    index === self.findIndex((t) => (t.save === arr.save && t.State === arr.State)))

console.log(clean);

您可以直接在chrome浏览器控制台进行尝试,并根据需要进行编辑。

我希望这对某些人有帮助。

票数 27
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23507853

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档