从JavaScript中的对象数组中删除重复项

Tra*_*vis 306 javascript arrays object duplicates

我有一个包含对象数组的对象.

things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});
Run Code Online (Sandbox Code Playgroud)

我想知道从数组中删除重复对象的最佳方法是什么.所以,例如,事情会变成......

{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}
Run Code Online (Sandbox Code Playgroud)

Eyd*_*ian 348

有些es6魔法怎么样?

things.thing = things.thing.filter((thing, index, self) =>
  index === self.findIndex((t) => (
    t.place === thing.place && t.name === thing.name
  ))
)
Run Code Online (Sandbox Code Playgroud)

参考网址

对于前端,这可能有点早到实现,因为许多使用的浏览器仍然不支持es6功能

  • 这可以简化为:`things.thing = things.thing.filter((thing,index,self)=> self.findIndex(t => t.place === thing.place && t.name === thing .name)=== index)` (67认同)
  • 如果您有一个包含 200,000 个条目的数组,那么这将需要 400 亿次迭代。这不应该与大型数组一起使用。始终使用地图。 (11认同)
  • @vsync只需要@BKM的答案并将它放在一起,通用的解决方案是:`const uniqueArray = arrayOfObjects.filter((object,index)=> index === arrayOfObjects.findIndex(obj => JSON.stringify(obj) === JSON.stringify(object)));`http://jsfiddle.net/x9ku0p7L/28/ (7认同)
  • 此处的关键是findIndex()方法返回** first **元素的索引,因此,如果有第二个元素匹配,则将永远不会在过滤器中找到并添加它。我盯着它看了一分钟:) (5认同)
  • 有一个问题,这不是一种 O(n^2) 方法吗?如果我处理 30 条记录,我会进行 900 次迭代,对吧?(最坏情况,不重复) (4认同)

aef*_*fxx 143

让我们看看...一个原始的:

var obj = {};

for ( var i=0, len=things.thing.length; i < len; i++ )
    obj[things.thing[i]['place']] = things.thing[i];

things.thing = new Array();
for ( var key in obj )
    things.thing.push(obj[key]);
Run Code Online (Sandbox Code Playgroud)

好吧,我认为应该这样做.看看,特拉维斯.

编辑
编辑代码以正确引用__CODE__(以前__CODE__)属性.

  • @aefxx我不太了解这个功能,你如何处理"地点"相同但名称不同的情况,是否应考虑重复? (12认同)
  • 你永远不应该在for循环中使用长度,因为它会减慢每次迭代计算它的速度.将它分配给循环外的变量并传递变量而不是things.thing.length. (7认同)
  • @DeepakGM 你说得对。答案不会(必然)保留给定的顺序。如果这是一项要求,则应寻找另一种解决方案。 (3认同)
  • 虽然这有效,但它不处理排序数组,因为从不保证获取键的顺序。因此,您最终再次对其进行排序。现在,假设数组没有排序但它的顺序很重要,你无法确保顺序保持不变 (2认同)

leo*_*ess 106

这是一个简短的 ES6 方法,其运行时间比已经存在的 65+ 个答案更好

let ids = array.map(o => o.id)
let filtered = array.filter(({id}, index) => !ids.includes(id, index + 1))
Run Code Online (Sandbox Code Playgroud)

例子:

let ids = array.map(o => o.id)
let filtered = array.filter(({id}, index) => !ids.includes(id, index + 1))
Run Code Online (Sandbox Code Playgroud)

这个怎么运作:

Array.filter()通过检查先前映射的 id-array 是否包含当前 id 来删除所有重复对象({id}将对象仅分解为它的 id)。要仅过滤出实际副本,它是使用Array.includes()的第二参数fromIndexindex + 1这将忽略当前对象和所有先前的。

由于filter回调方法的每次迭代只会搜索从当前索引 + 1 开始的数组,这也大大减少了运行时间,因为只有先前未过滤的对象才会被检查。

这显然也适用于任何其他未被调用的键,id甚至多个或所有键。

  • 好问题,@Timotronadon。`{ id }` 是将对象解构为仅其 `id` 键。为了说明这一点,让我们看一下这两个循环: 1. `arr.forEach(object =&gt; console.log(object.id))` 和 2. `arr.forEach({id} =&gt; console.log(id)) `。它们都在做完全相同的事情:打印“arr”中所有对象的“id”键。然而,一种是使用解构,另一种是通过点表示法使用更传统的键访问。 (4认同)
  • def 这里是最好的回应。简单干净优雅,很有魅力,谢谢! (4认同)
  • @user239558好问题,但不是真的,对于具有不同顺序的对象(如“{id:1,name:'one'}”和“{namd:'one',id:1}”),速度会慢几个数量级它将无法检测到重复项。 (2认同)
  • 惊人的答案。这在不使用任何外部库的情况下完美地工作了。 (2认同)

amb*_*odi 91

如果您可以使用Javascript库,例如下划线或lodash,我建议您查看_.uniq其库中的函数.来自lodash:

_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])
Run Code Online (Sandbox Code Playgroud)

基本上,你传入的数组在这里是一个对象文字,你传入要在原始数据数组中删除重复项的属性,如下所示:

var data = [{'name': 'Amir', 'surname': 'Rahnama'}, {'name': 'Amir', 'surname': 'Stevens'}];
var non_duplidated_data = _.uniq(data, 'name'); 
Run Code Online (Sandbox Code Playgroud)

更新:Lodash现在也推出了一款.uniqBy.

  • 注意:你现在需要使用`uniqBy`而不是`uniq`,例如`_.uniqBy(data,'name')`...文档:https://lodash.com/docs#uniqBy (20认同)
  • @Praveen Pds:我在代码示例中是否有任何关于下划线的内容?我说'lodash'有这个功能,下划线有类似的功能.在投票之前,请仔细阅读答案. (3认同)

Jam*_*ard 69

我有完全相同的要求,根据单个字段上的重复项删除数组中的重复对象.我在这里找到了代码:Javascript:从对象数组中删除重复项

所以在我的例子中,我正在从数组中删除任何具有重复的licenseNum字符串值的对象.

var arrayWithDuplicates = [
    {"type":"LICENSE", "licenseNum": "12345", state:"NV"},
    {"type":"LICENSE", "licenseNum": "A7846", state:"CA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"OR"},
    {"type":"LICENSE", "licenseNum": "10849", state:"CA"},
    {"type":"LICENSE", "licenseNum": "B7037", state:"WA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"NM"}
];

function removeDuplicates(originalArray, prop) {
     var newArray = [];
     var lookupObject  = {};

     for(var i in originalArray) {
        lookupObject[originalArray[i][prop]] = originalArray[i];
     }

     for(i in lookupObject) {
         newArray.push(lookupObject[i]);
     }
      return newArray;
 }

var uniqueArray = removeDuplicates(arrayWithDuplicates, "licenseNum");
console.log("uniqueArray is: " + JSON.stringify(uniqueArray));
Run Code Online (Sandbox Code Playgroud)

结果:

uniqueArray是:

[{"type":"LICENSE","licenseNum":"10849","state":"CA"},
{"type":"LICENSE","licenseNum":"12345","state":"NM"},
{"type":"LICENSE","licenseNum":"A7846","state":"CA"},
{"type":"LICENSE","licenseNum":"B7037","state":"WA"}]
Run Code Online (Sandbox Code Playgroud)


chi*_*ens 37

一张带地图的班轮(高性能,不保留顺序)

查找id数组中唯一的arr

const arrUniq = [...new Map(arr.map(v => [v.id, v])).values()]
Run Code Online (Sandbox Code Playgroud)

如果顺序很重要,请查看带过滤器的解决方案:带过滤器的解决方案


数组中多个属性 (place和) 唯一namearr

const arrUniq = [...new Map(arr.map(v => [JSON.stringify([v.place,v.name]), v])).values()]
Run Code Online (Sandbox Code Playgroud)

数组中所有属性都是唯一的arr

const arrUniq = [...new Map(arr.map(v => [JSON.stringify(v), v])).values()]
Run Code Online (Sandbox Code Playgroud)

保留数组中第一次出现的位置arr

const arrUniq = [...new Map(arr.slice().reverse().map(v => [v.id, v])).values()].reverse()
Run Code Online (Sandbox Code Playgroud)


Mμ.*_*Mμ. 34

一个班轮使用Set

var things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

// assign things.thing to myData for brevity
var myData = things.thing;

things.thing = Array.from(new Set(myData.map(JSON.stringify))).map(JSON.parse);

console.log(things.thing)
Run Code Online (Sandbox Code Playgroud)

说明:

  1. new Set(myData.map(JSON.stringify))使用字符串化的myData元素创建一个Set对象.
  2. Set对象将确保每个元素都是唯一的.
  3. 然后我使用Array.from基于创建集的元素创建一个数组.
  4. 最后,我使用JSON.parse将字符串化元素转换回对象.

  • 问题是{a:1,b:2}不等于{b:2,a:1} (10认同)
  • 请记住,Date 属性会出现问题 (2认同)

小智 25

如果您只需要通过对象的一个​​字段进行比较,则可以使用Array迭代方法执行此操作的另一个选项:

    function uniq(a, param){
        return a.filter(function(item, pos, array){
            return array.map(function(mapItem){ return mapItem[param]; }).indexOf(item[param]) === pos;
        })
    }

    uniq(things.thing, 'place');
Run Code Online (Sandbox Code Playgroud)


mac*_*llt 22

如果您可以等到所有添加之后消除重复项,则典型的方法是首先对数组进行排序,然后消除重复项.排序避免了在遍历它们时扫描每个元素的数组的N*N方法.

"消除重复"功能通常称为uniqueuniq.一些现有实现可以组合这两个步骤,例如原型的uniq

如果您的图书馆还没有,那么这篇文章几乎没有想过尝试(有些要避免:-))!我个人觉得这个最直接:

    function unique(a){
        a.sort();
        for(var i = 1; i < a.length; ){
            if(a[i-1] == a[i]){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }  

    // Provide your own comparison
    function unique(a, compareFunc){
        a.sort( compareFunc );
        for(var i = 1; i < a.length; ){
            if( compareFunc(a[i-1], a[i]) === 0){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }
Run Code Online (Sandbox Code Playgroud)


sra*_*nji 20

一个班轮在这里

let arr = [
  {id:1,name:"sravan ganji"},
  {id:2,name:"anu"},
  {id:4,name:"mammu"},
  {id:3,name:"sanju"},
  {id:3,name:"ram"},
];

console.log(Object.values(arr.reduce((acc,cur)=>Object.assign(acc,{[cur.id]:cur}),{})))
Run Code Online (Sandbox Code Playgroud)

  • 如果您只想删除具有单个重复值的对象,则很好且干净,而对于完全重复的对象则不那么干净。 (6认同)

аle*_*kyі 19

var uniq = {}
var arr  = [{"id":"1"},{"id":"1"},{"id":"2"}]
var arrFiltered = arr.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));
console.log('arrFiltered', arrFiltered)
Run Code Online (Sandbox Code Playgroud)

  • Stack Overflow是一个很好的做法,可以解释为什么你的解决方案应该有效,特别是你的解决方案比其他答案更好.有关更多信息,请阅读[如何回答](// stackoverflow.com/help/how-to-answer). (5认同)

chi*_*ens 16

ES6 +的最短衬管

id在数组中查找唯一的。

arr.filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i)
Run Code Online (Sandbox Code Playgroud)

通过多个属性(placename)唯一

arr.filter((v,i,a)=>a.findIndex(t=>(t.place === v.place && t.name===v.name))===i)
Run Code Online (Sandbox Code Playgroud)

Unique by all properties (This will be slow for large arrays)

arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)
Run Code Online (Sandbox Code Playgroud)

Keep the last occurrence. Add slice and reverse to beginning and reverse again in the end.

arr.slice().reverse().filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i).reverse()
Run Code Online (Sandbox Code Playgroud)

  • v,i,a == 值、索引、数组 (24认同)
  • 如果能解释一下它们的作用就更好了。如果他们使用清晰的命名约定而不是尝试预先缩小代码。 (5认同)
  • arr.filter((v,i,a)=&gt;a.findIndex(t=&gt;(JSON.stringify(t) === JSON.stringify(v)))===i) 如果键这将不起作用顺序不同 (2认同)

Tim*_*own 14

更新

我现在已经正确地阅读了这个问题.这是执行此操作的一般方法:传入一个函数,该函数测试数组的两个元素是否相等.在这种情况下,它会比较被比较的两个对象的值nameplace属性.

function removeDuplicates(arr, equals) {
    var originalArr = arr.slice(0);
    var i, len, j, val;
    arr.length = 0;

    for (i = 0, len = originalArr.length; i < len; ++i) {
        val = originalArr[i];
        if (!arr.some(function(item) { return thingsEqual(item, val); })) {
            arr.push(val);
        }
    }
}

function thingsEqual(thing1, thing2) {
    return thing1.place === thing2.place
        && thing1.name === thing2.name;
}

var things = [
  {place:"here",name:"stuff"},
  {place:"there",name:"morestuff"},
  {place:"there",name:"morestuff"}
];

removeDuplicates(things, thingsEqual);
console.log(things);
Run Code Online (Sandbox Code Playgroud)


Pet*_*e B 13

要再向列表中添加一个.使用ES6并Array.reduceArray.find.
在此示例中,基于guid属性过滤对象.

let filtered = array.reduce((accumulator, current) => {
  if (! accumulator.find(({guid}) => guid === current.guid)) {
    accumulator.push(current);
  }
  return accumulator;
}, []);
Run Code Online (Sandbox Code Playgroud)

扩展这个以允许选择属性并将其压缩成一个衬里:

const uniqify = (array, key) => array.reduce((prev, curr) => prev.find(a => a[key] === curr[key]) ? prev : prev.push(curr) && prev, []);
Run Code Online (Sandbox Code Playgroud)

要使用它,请传递一个对象数组以及您希望作为字符串值进行重复数据删除的键的名称:

const result = uniqify(myArrayOfObjects, 'guid')
Run Code Online (Sandbox Code Playgroud)


dgk*_*nca 13

我认为最好的方法是使用reduceMap object这是单线解决方案。

const data = [
  {id: 1, name: 'David'},
  {id: 2, name: 'Mark'},
  {id: 2, name: 'Lora'},
  {id: 4, name: 'Tyler'},
  {id: 4, name: 'Donald'},
  {id: 5, name: 'Adrian'},
  {id: 6, name: 'Michael'}
]

const uniqueData = [...data.reduce((map, obj) => map.set(obj.id, obj), new Map()).values()];

console.log(uniqueData)

/*
  in `map.set(obj.id, obj)`
  
  'obj.id' is key. (don't worry. we'll get only values using the .values() method)
  'obj' is whole object.
*/
Run Code Online (Sandbox Code Playgroud)

  • 通过删除行之间的回车符和/或换行符,任何东西都可以成为“单行解决方案”:P。 (3认同)

Pra*_*eek 11

你也可以使用Map:

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());
Run Code Online (Sandbox Code Playgroud)

完整样本:

const things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

console.log(JSON.stringify(dedupThings, null, 4));
Run Code Online (Sandbox Code Playgroud)

结果:

[
    {
        "place": "here",
        "name": "stuff"
    },
    {
        "place": "there",
        "name": "morestuff"
    }
]
Run Code Online (Sandbox Code Playgroud)


V. *_*bor 11

在一行中使用ES6,您可以通过按键获得对象的唯一列表:

const unique = [...new Map(arr.map(item => [item[key], item])).values()]
Run Code Online (Sandbox Code Playgroud)

可以将其放入函数中,并在以下示例中使用:

const unique = [...new Map(arr.map(item => [item[key], item])).values()]
Run Code Online (Sandbox Code Playgroud)

  • TS 版本,以防有人在看:```export const unique = &lt;T extends { [key: string]:unknown }&gt;(arr: T[], key: string): T[] =&gt; [ ...new Map(arr.map((item: T) =&gt; [item[key], item])).values() ]; ```` (9认同)
  • 嗨@DavidSchumann,我将更新答案并解释它是如何工作的。但对于简短的回答,顺序被保留,第一个被删除...只要想想它是如何插入到地图中的...它检查密钥是否已经存在,它将更新它,因此最后一个将保留 (3认同)

Mas*_*iri 11

为懒惰的Typescript开发人员提供快速(运行时间较短)和类型安全的答案:

export const uniqueBy = <T>( uniqueKey: keyof T, objects: T[]): T[] => {
  const ids = objects.map(object => object[uniqueKey]);
  return objects.filter((object, index) => !ids.includes(object[uniqueKey], index + 1));
} 
Run Code Online (Sandbox Code Playgroud)


Cli*_*all 10

Dang,孩子们,让我们粉碎这件事,为什么不呢?

let uniqIds = {}, source = [{id:'a'},{id:'b'},{id:'c'},{id:'b'},{id:'a'},{id:'d'}];
let filtered = source.filter(obj => !uniqIds[obj.id] && (uniqIds[obj.id] = true));
console.log(filtered);
// EXPECTED: [{id:'a'},{id:'b'},{id:'c'},{id:'d'}];
Run Code Online (Sandbox Code Playgroud)

  • 这是对上述问题的概括的改进。最初的问题是 9 年前发布的,所以最初的发布者今天可能不担心“地点”和“名称”。阅读此主题的任何人都在寻找一种对对象列表进行重复数据删除的最佳方法,这是一种紧凑的方法。 (2认同)

小智 10

TypeScript解决方案

这将删除重复的对象,并保留对象的类型。

function removeDuplicateObjects(array: any[]) {
  return [...new Set(array.map(s => JSON.stringify(s)))]
    .map(s => JSON.parse(s));
}
Run Code Online (Sandbox Code Playgroud)

  • 当你有对象时,停止使用 stringify!天哪,这就是我不喜欢 JS 的原因,它让人们做各种丑陋的事情。 (5认同)
  • 使用“any”类型完全违背了 TypeScript 的目的 (4认同)
  • 这是伟大的和短暂的! (2认同)

小智 10

如果数组包含对象,那么您可以使用它来删除重复的

const persons= [
      { id: 1, name: 'John',phone:'23' },
      { id: 2, name: 'Jane',phone:'23'},
      { id: 1, name: 'Johnny',phone:'56' },
      { id: 4, name: 'Alice',phone:'67' },
    ];
const unique = [...new Map(persons.map((m) => [m.id, m])).values()];
Run Code Online (Sandbox Code Playgroud)

如果在phone的基础上去重,只需将m.id替换为m.phone即可

const unique = [...new Map(persons.map((m) => [m.phone, m])).values()];
Run Code Online (Sandbox Code Playgroud)


نور*_*نور 9

 const things = [
  {place:"here",name:"stuff"},
  {place:"there",name:"morestuff"},
  {place:"there",name:"morestuff"}
];
const filteredArr = things.reduce((thing, current) => {
  const x = thing.find(item => item.place === current.place);
  if (!x) {
    return thing.concat([current]);
  } else {
    return thing;
  }
}, []);
console.log(filteredArr)
Run Code Online (Sandbox Code Playgroud)

通过Set对象解决方案| 根据数据类型

const seen = new Set();
 const things = [
  {place:"here",name:"stuff"},
  {place:"there",name:"morestuff"},
  {place:"there",name:"morestuff"}
];

const filteredArr = things.filter(el => {
  const duplicate = seen.has(el.place);
  seen.add(el.place);
  return !duplicate;
});
console.log(filteredArr)
Run Code Online (Sandbox Code Playgroud)

Set 对象特征

Set Object 中的每个值都必须是唯一的,将检查值是否相等

Set 对象的目的是根据数据类型存储唯一值,无论是原始值还是对象引用。它有四个非常有用的实例方法add, clear, has& delete

唯一和数据类型功能:...

add方法

默认情况下,它会将唯一数据推送到集合中并保留数据类型..这意味着它可以防止将重复项推送到集合中,并且默认情况下它还会检查数据类型...

has 方法

有时需要检查数据项是否存在于集合中,并且 . 这是集合确定唯一 id 或项目和数据类型的方便方法..

delete 方法

它将通过识别数据类型从集合中删除特定项目..

clear 方法

它将从一个特定变量中删除所有集合项并设置为空对象

Set对象也有迭代方法和更多功能..

更好地从这里阅读: 设置 - JavaScript | MDN


Jac*_*ine 8

这种方式对我很有效:

function arrayUnique(arr, uniqueKey) {
  const flagList = new Set()
  return arr.filter(function(item) {
    if (!flagList.has(item[uniqueKey])) {
      flagList.add(item[uniqueKey])
      return true
    }
  })
}
const data = [
  {
    name: 'Kyle',
    occupation: 'Fashion Designer'
  },
  {
    name: 'Kyle',
    occupation: 'Fashion Designer'
  },
  {
    name: 'Emily',
    occupation: 'Web Designer'
  },
  {
    name: 'Melissa',
    occupation: 'Fashion Designer'
  },
  {
    name: 'Tom',
    occupation: 'Web Developer'
  },
  {
    name: 'Tom',
    occupation: 'Web Developer'
  }
]
console.table(arrayUnique(data, 'name'))// work well
Run Code Online (Sandbox Code Playgroud)

打印

????????????????????????????????????????????
? (index) ?   name    ?     occupation     ?
????????????????????????????????????????????
?    0    ?  'Kyle'   ? 'Fashion Designer' ?
?    1    ?  'Emily'  ?   'Web Designer'   ?
?    2    ? 'Melissa' ? 'Fashion Designer' ?
?    3    ?   'Tom'   ?  'Web Developer'   ?
????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

ES5:

function arrayUnique(arr, uniqueKey) {
  const flagList = []
  return arr.filter(function(item) {
    if (flagList.indexOf(item[uniqueKey]) === -1) {
      flagList.push(item[uniqueKey])
      return true
    }
  })
}
Run Code Online (Sandbox Code Playgroud)

这两种方式更简单,更容易理解。


小智 6

另一种选择是创建一个自定义indexOf函数,该函数比较每个对象所选属性的值,并将其包含在reduce函数中.

var uniq = redundant_array.reduce(function(a,b){
      function indexOfProperty (a, b){
          for (var i=0;i<a.length;i++){
              if(a[i].property == b.property){
                   return i;
               }
          }
         return -1;
      }

      if (indexOfProperty(a,b) < 0 ) a.push(b);
        return a;
    },[]);
Run Code Online (Sandbox Code Playgroud)


Jus*_*tin 6

考虑到 lodash.uniqWith

var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];

_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
Run Code Online (Sandbox Code Playgroud)


小智 6

这是 ES6 的解决方案,您只想保留最后一项。该解决方案功能齐全且符合 Airbnb 风格。

const things = {
  thing: [
    { place: 'here', name: 'stuff' },
    { place: 'there', name: 'morestuff1' },
    { place: 'there', name: 'morestuff2' }, 
  ],
};

const removeDuplicates = (array, key) => {
  return array.reduce((arr, item) => {
    const removed = arr.filter(i => i[key] !== item[key]);
    return [...removed, item];
  }, []);
};

console.log(removeDuplicates(things.thing, 'place'));
// > [{ place: 'here', name: 'stuff' }, { place: 'there', name: 'morestuff2' }]
Run Code Online (Sandbox Code Playgroud)


Sна*_*ƒаӽ 6

我知道这个问题已经有很多答案了,但请耐心等待...

数组中的某些对象可能具有您不感兴趣的其他属性,或者您只想查找仅考虑属性子集的唯一对象。

考虑下面的数组。假设您只想在此数组中查找唯一对象propOnepropTwo,并忽略可能存在的任何其他属性。

预期结果应仅包括第一个和最后一个对象。所以这里是代码:

const array = [{
    propOne: 'a',
    propTwo: 'b',
    propThree: 'I have no part in this...'
},
{
    propOne: 'a',
    propTwo: 'b',
    someOtherProperty: 'no one cares about this...'
},
{
    propOne: 'x',
    propTwo: 'y',
    yetAnotherJunk: 'I am valueless really',
    noOneHasThis: 'I have something no one has'
}];

const uniques = [...new Set(
    array.map(x => JSON.stringify(((o) => ({
        propOne: o.propOne,
        propTwo: o.propTwo
    }))(x))))
].map(JSON.parse);

console.log(uniques);
Run Code Online (Sandbox Code Playgroud)


Mar*_*rkN 5

removeDuplicates()接收一个对象数组,并返回一个没有任何重复对象的新数组(基于id属性)。

const allTests = [
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'},
  {name: 'Test2', id: '2'},
  {name: 'Test3', id: '3'}
];

function removeDuplicates(array) {
  let uniq = {};
  return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true))
}

removeDuplicates(allTests);
Run Code Online (Sandbox Code Playgroud)

预期结果:

[
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'}
];
Run Code Online (Sandbox Code Playgroud)

首先,我们将变量uniq的值设置为一个空对象。

接下来,我们筛选对象数组。筛选器会创建一个新数组,其中包含所有通过提供的功能实现的测试的元素。

return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));
Run Code Online (Sandbox Code Playgroud)

上面,我们使用&&的短路功能。如果&&的左侧求值为true,则返回&&右侧的值。如果左侧为假,则返回&&左侧的内容。

对于每个object(obj),我们都会在uniq中检查名为obj.id的值的属性(在这种情况下,在第一次迭代中它将检查属性'1'。)我们想要返回的结果与之相反(或者为true或false),这就是我们使用!的原因 在!uniq [obj.id]中。如果uniq已经具有id属性,则返回true,结果为false(!),告诉过滤器函数不要添加该obj。但是,如果找不到obj.id属性,它将返回false,然后求值为true(!),并返回&&或(uniq [obj.id] = true)右边的所有内容。这是一个真实值,它告诉filter方法将该obj添加到返回的数组中,并且还将属性{1:true}添加到uniq中。这样可以确保不会再添加任何其他具有相同ID的obj实例。


Sav*_*ari 5

let myData = [{place:"here",name:"stuff"}, 
 {place:"there",name:"morestuff"},
 {place:"there",name:"morestuff"}];


let q = [...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];

console.log(q)
Run Code Online (Sandbox Code Playgroud)

使用ES6和的单线new Map()

// assign things.thing to myData
let myData = things.thing;

[...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];
Run Code Online (Sandbox Code Playgroud)

细节:-

  1. 这样做.map()的数据列表和每个单独的对象转换成[key, value]一对阵列(长度= 2),所述第一元件(键)将是stringified所述对象的版本和第二(值)将是一个object本身。
  2. 将上面创建的数组列表添加到new Map()会将键作为stringified对象,并且添加任何相同的键都将导致覆盖已经存在的键。
  3. 使用.values()将为MapIterator提供Map中的所有值(obj在我们的示例中)
  4. 最后,spread ...操作员使用上述步骤中的值为新数组赋值。