从数组中删除所有出现多次的元素

时间:2018-10-30 14:42:18

标签: javascript ecmascript-6

在人们认为这与Stack Overflow上关于删除重复项的所有其他答案相同之前,您能否先看一下返回的内容而不是我想要做的事情。

我想删除所有出现多次的元素。我尝试了以下方法:

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];

const uniqueArray = a.filter(function(item, pos) {
  return a.indexOf(item) == pos;
})

console.log(uniqueArray)

我希望我的uniqueArray

['Ronaldo', 'Maradona', 'Messi'];

5 个答案:

答案 0 :(得分:5)

简而言之:如果第一次出现的元素(indexOf)的位置也是数组(lastIndexOf)中元素的最后位置,则保留该值。

如果索引不相等,则该值将重复,您可以将其丢弃。

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 
           'Pele', 'Messi', 'Jair', 'Baggio', 'Messi', 
           'Seedorf'];

const uniqueArray = a.filter(function(item, pos) {
  return a.lastIndexOf(item) == a.indexOf(item);
});

console.log(uniqueArray);
/* output:  ["Ronaldo", "Maradona", "Jair", "Baggio", "Seedorf"] */
  

Codepen Demo

答案 1 :(得分:2)

您可以在每次迭代中计算项目,以便可以将其包括在条件中:

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];

const uniqueArray = a.filter(function(item, pos) {
  var c = a.filter(i => i==item).length;
  return a.indexOf(item) == pos && c <= 1;
})

console.log(uniqueArray);

更好的解决方案是将当前数组项的索引与Array.prototype.indexOf()Array.prototype.lastIndexOf()进行比较:

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];

const uniqueArray = a.filter(function(item, pos) {
  return a.indexOf(item) === a.lastIndexOf(item);
})

console.log(uniqueArray);

答案 2 :(得分:0)

天真的方法是检查不止一种情况:

   a.filter((el, i) => !(a.indexOf(el) !== i || a.indexOf(el, i) > -1)));

或更复杂的一组多个(但O(n)):

  const found = new Set, values = new Set;

  for(const el of a)
   if(!found.has(el)) {
     found.add(el);
     values.add(el);
   } else if(values.has(el) {
     values.delete(el);
   }
 }

 const result = [...values.values()];

答案 3 :(得分:0)

您可以使用Map来计数每个条目出现的次数,然后仅取一次的次数。

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];

const uniqueArray = onlyUniqueItems(a);

console.log(uniqueArray)


function onlyUniqueItems(array) {
  const map = new Map();
  const result = [];
  
  array.forEach(item => {
    let amount = map.get(item) || 0;
    map.set(item, ++amount); //pre-increment and then set the amount
  });
  
  map.forEach((amount, item) => {
    if (amount == 1) {
      result.push(item);
    }
  });
  
  return result;
}

这将在O(2n)中运行,因为您最多必须进行两次扫描。您可以使用一个普通对象并在其上设置键值来获得类似的结果,但是Map的优点是保留了您拥有的项的类型,而普通对象会将所有键都转换为字符串:

const a = [1, 2, 3, 3, "4", "4", "5"];

const uniqueArray = onlyUniqueItems(a);
const uniqueArrayUsingObject = onlyUniqueItemsUsingObject(a);

console.log(uniqueArray)
console.log(uniqueArrayUsingObject)


function onlyUniqueItems(array) {
  const map = new Map();
  const result = [];
  
  //count occurences
  array.forEach(item => {
    let amount = map.get(item) || 0;
    map.set(item, ++amount); //pre-increment and then set the amount
  });
  
  //extract only the items that show once
  map.forEach((amount, item) => {
    if (amount == 1) {
      result.push(item);
    }
  });
  
  return result;
}


function onlyUniqueItemsUsingObject(array) {
  const map = {};
  const result = [];
  
  //count occurences
  array.forEach(item => {
    let amount = map[item] || 0;
    map[item] = ++amount; //pre-increment and then set the amount
  });
  
  //extract only the items that show once
  Object.entries(map).forEach(([item, amount]) => {
    if (amount == 1) {
      result.push(item);
    }
  });
  
  return result;
}

答案 4 :(得分:-1)

为什么不使用Set

const theSet = new Set(a);
const values = set.values();
const uniqueArray = Array.from(values);