从数组中删除重复项

时间:2016-12-28 14:49:10

标签: javascript arrays

我有一个对象数组,如下所示:

var array = [
    {id:123, value:"value1", name:"Name1"},
    {id:124, value:"value2", name:"Name1"},
    {id:125, value:"value3", name:"Name2"},
    {id:126, value:"value4", name:"Name2"}
    ...
];

如您所见,某些名称会重复出现。我想获得一个只有名字的新数组,但是如果某些名称重复,我不想再添加它。我想要这个数组:

var newArray = ["Name1", "Name2"];

我正在尝试使用map执行此操作:

var newArray = array.map((a) => {
    return a.name;
});

但问题是这会返回:

newArray = ["Name1", "Name1", "Name2", "Name2"];

如何在map内设置一些条件,因此它不会返回已存在的元素?我想用map或其他一些ECMAScript 5或ECMAScript 6功能来做到这一点。

17 个答案:

答案 0 :(得分:178)

使用ES6,在仅映射对象的名称后,可以使用Set作为唯一值。

此提案使用spread syntax ...收集新数组中的项目。



const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }],
      names = [...new Set(array.map(a => a.name))];

console.log(names);




答案 1 :(得分:58)

如果您正在寻找非ES 6(无设置)的JavaScript解决方案,您可以使用Array's reduce method

var array=[
  {id:123, value:"value1", name:"Name1"},
  {id:124, value:"value2", name:"Name1"},
  {id:125, value:"value3", name:"Name2"},
  {id:126, value:"value4", name:"Name2"}
];
var names = array.reduce(function (a, b) {
  if (a.indexOf(b.name) == -1) {
    a.push(b.name)
  }
  return a;
}, []);

console.log(names);

答案 2 :(得分:16)

就我个人而言,我不明白为什么每个人都对ES 6感兴趣。如果是我的代码,我宁愿支持尽可能多的浏览器。

var array=[
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
];

   // Create array of unique names
var a = (function(a){
  for (var i = array.length; i--;)
    if (a.indexOf(array[i].name) < 0) a.push(array[i].name);
  return a;
})([]);

console.log(a);

答案 3 :(得分:12)

您也可以简单地将mapfilter

合并

var array = [
  {id:123, value:"value1", name:"Name1"},
  {id:124, value:"value2", name:"Name1"},
  {id:125, value:"value3", name:"Name2"},
  {id:126, value:"value4", name:"Name2"}
];

var unique = array
  .map( item => item.name )
  .filter( ( item, idx, arr ) => arr.indexOf( item ) == idx ) 

console.log(unique)

答案 4 :(得分:9)

您可以Array.prototype.map()使用参数nameelem和{{1}来获取包含index属性而不是Array.prototype.filter()的数组的数组在函数谓词中,消除重复的元素:

&#13;
&#13;
array
&#13;
&#13;
&#13;

答案 5 :(得分:6)

我同意,如果您只需要chcp值,则name即可。

然而,如果您想根据Set属性获取一系列唯一对象,我建议您使用Map。创建Map的快速方法是通过name数组的数组:

&#13;
&#13;
[key, value]
&#13;
const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }],
      unique = new Map(array.map(obj => [obj.name, obj]));

// To get the unique objects
const uniques = Array.from(unique.values());

// Get the names like you already did:
console.log("Names:", uniques.map(obj => obj.name));

// If you ever need the complete array of unique objects, you got a ref:
console.log(JSON.stringify(uniques));
&#13;
&#13;
&#13;

.as-console-wrapper { min-height: 100%; }的另一个好处是,您可以获得切断非唯一身份的Map功能,而不会丢失与源对象的连接。当然,只有在需要多次引用唯一的对象集时才需要它。

答案 6 :(得分:6)

这里有很多好的答案。我只想提供一些多样性,希望能给你另一种观点。

数组在JavaScript中是对象类型,因此它们可以同时用作哈希。通过使用此功能,我们可以极大地简化在O(n)时间复杂度的单个reduce操作中完成的工作。

如果您对包含数组键以外的某些属性的数组不满意,可以考虑保留一个单独的哈希对象。

right-click

答案 7 :(得分:3)

如果您仅限于ES5,我会使用Lodash's _.uniq

var newArray = _.uniq(array.map(function(a) {
  return a.name;
}));

答案 8 :(得分:2)

使用ES6,这应该可以胜任。

&#13;
&#13;
var array=[
    {id:123, value:"value1", name:"Name1"},
    {id:124, value:"value2", name:"Name1"},
    {id:125, value:"value3", name:"Name2"},
    {id:126, value:"value4", name:"Name2"}
];

var set = new Set();

array.forEach((a)=>{
    set.add(a.name);
}); 

console.log(Array.from(set));
&#13;
&#13;
&#13;

答案 9 :(得分:1)

使用UnderscoreJS,

&#13;
&#13;
array = [{id:123, value:"value1", name:"Name1"}, {id:124, value:"value2", name:"Name1"}, {id:125, value:"value3", name:"Name2"}, {id:126, value:"value4", name:"Name2"}];
get_names =  _.pluck(_.uniq(array, 'name'), 'name')
console.log(get_names)
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

`

答案 10 :(得分:0)

试试这个:

nArr = [];
array.forEach((a) => {
    if (nArr.indexOf(a.name) < 0) { 
        nArr.push(a.name); 
    }
}); 

答案 11 :(得分:0)

我是怎么做到的,使用一个单独的空数组。

&#13;
&#13;
var array = [
   {id:123, value:"value1", name:"Name1"},
   {id:124, value:"value2", name:"Name1"},
   {id:125, value:"value3", name:"Name2"},
   {id:126, value:"value4", name:"Name2"}	    
];

var array2 = []		
		
for (i=0; i<array.length;i++){						
   if (array2.indexOf(array[i].name) == -1){				
     array2.push(array[i].name);
    }
}			

console.log(array2)	
&#13;
&#13;
&#13;

答案 12 :(得分:0)

在ES5中,使用对象作为O( n )性能的字典。

仅当所有键都是字符串时才会起作用。

var array = [
    {id: 123, value: "value1", name: "Name1"},
    {id: 124, value: "value2", name: "Name1"},
    {id: 125, value: "value3", name: "Name2"},
    {id: 126, value: "value4", name: "Name2"}
];

var allNames = array.map(item => item.name);

var map = {};
allNames.forEach(name => {
  map[name] = true;
});
var uniqueNames = Object.keys(map);

console.log(uniqueNames);

如果您愿意,可以在一个表达式中执行相同的操作:

var uniqueNames = Object.keys(allNames.reduce((m, n) => (m[n] = true, m), {}));

但我发现命令式表格更容易阅读。

答案 13 :(得分:0)

如果要最大兼容性,请使用像这样的array#forEach()array#indexOf()方法,简洁的语法:

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }]

// initialize an empty array named names
let names = [];

// iterate through every element of `array` & check if it's 'name' key's value already in names array if not ADD it 
array.forEach(function(element) { if (names.indexOf(element.name) === -1) names.push(element.name) });
// or use tilde like this:
//array.forEach(function(element) { if (~names.indexOf(element.name)) names.push(element.name) });

console.log(names);

但是,如果兼容性不是问题 ,请使用 ECMAScript 6 Set对象,array#mapArray.from()方法

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }];

// iterate through every element from array using map and store it in Set(a Set won't have duplicates) then convert the Set back to Array(using Array.from)
let names = Array.from(new Set(array.map(element => element.name)));

console.log(names);

答案 14 :(得分:0)

我看到有很多类似扩展集的解决方案,但都不是最优的。

这个解决方案更简单、更高效,而且不需要重新创建数组:

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }]

const res = array.map(e => e.name)
                 .filter((e, i, a) => a.indexOf(e) == i)

console.log(res)

答案 15 :(得分:-1)

对于那些寻求1班轮的人

const names = array.reduce((acc, {name}) => acc.includes(name) ? acc : [name, ...acc], []);

或不使用阵列原型上的方法

const { reduce, includes } = Array;
const names = reduce(array, (acc, {name}) => includes(acc, name) ? acc : [name, ...acc], []);

可以用于编写一些纯函数来处理这个

const get_uniq_values = (key, arr) => reduce(arr, (a, o) => includes(a, o[key]) ? a : [o[key], ...a], []);

答案 16 :(得分:-1)

var __array=[{id:123, value:"value1", name:"Name1"},{id:124, value:"value2", name:"Name1"},{id:125, value:"value3", name:"Name2"},{id:126, value:"value4", name:"Name2"}];

function __checkArray(__obj){
    var flag = true;
    for(let i=0; i < __array.length; i++){
        if(__obj.id == __array.id){
            flag = false;
            break;
        }
    }

    return flag;
}

var __valToPush = {id: 127, value: "value5", name: "Name3"};
if(__checkArray(__valToPush)){
    __array.push(__valToPush)
}