从数组中完全移除重复项

4

假设我有以下内容:

var array = [1,2,3,4,4,5,5];

我希望您可以将其实现;
var newArray = [1,2,3];

我希望完全删除重复项,而不是将它们保留为唯一值。通过reduce方法有办法实现吗?


5
可能是 Remove Duplicates from JavaScript Array 的重复问题。 - Stéphane Bruckert
1
为什么不使用过滤器? - Nina Scholz
1
请澄清一下,如果一个数字出现了多次,您想要删除该数字的所有实例 - 是这样吗?因此,您期望的输出将是 [1,2,3] - mhodges
@mhodges 兄弟,你删掉了“有没有办法通过reduce方法实现这个目的?”这句话,完全改变了问题的目的。 - kind user
1
@Kinduser 大多数 OP 不知道他们不知道什么。你必须给他们以怀疑的好处。我就放在这里 - mhodges
显示剩余6条评论
11个回答

20
你可以使用 Array#filter 连接 Array#indexOfArray#lastIndexOf,并仅返回共享相同索引的值。

var array = [1, 2, 3, 4, 4, 5, 5],
    result = array.filter(function (v, _, a) {
        return a.indexOf(v) === a.lastIndexOf(v);
    });

console.log(result);

另一种方法是使用 Map,将值设置为false,如果之前已经见过该键。然后通过获取映射的值来过滤数组。

var array = [1, 2, 3, 4, 4, 5, 5],
    result = array.filter(
        Map.prototype.get,
        array.reduce((m, v) => m.set(v, !m.has(v)), new Map)
    );

console.log(result);


没想到用 lastIndexOf - 很棒的解决方案! - mhodges
1
这很棒。我也没有想到lastIndexOf。 - Ozan
1
不错!第二个例子在算法顺序方面更好;而且它在过滤器中使用了thisArg的非常巧妙的方法,我通过阅读答案才学到。谢谢! - Diego

2

我猜它性能不会太出色,但我喜欢这个想法。

var array = [1,2,3,4,4,5,5],
    res = array.reduce(function(s,a) {
      if (array.filter(v => v !== a).length == array.length-1) {
        s.push(a);
      }
      return s;
    }, []);
    console.log(res);


0

我的答案使用了以下的map和filter:

x = [1,2,3,4,2,3]
x.map(d => x.filter(i => i == d).length < 2 ? d : null).filter(d => d != null)
// [1, 4]

0

Object.values自ES2017开始得到支持(不用说 - 不支持IE)。 累加器是一个对象,其中每个键都是一个值,因此重复的键会被覆盖并删除。 然而,这种解决方案可能会在处理不良值(null、undefined等)时存在风险,但在实际场景中可能很有用。

let NukeDeps = (arr) => {
  return Object.values(arr.reduce((curr, i) => {
    curr[i] = i;
    return curr;
  }, {}))  
}

0
另一个选择是使用对象来跟踪元素的使用次数。这将破坏数组顺序,但在非常大的数组上应该更快。

function nukeDuplications(arr) {
  const hash = {};
  arr.forEach(el => {
    const qty = hash[el] || 0;
    hash[el] = qty+1;
  });
  
  const ret = [];
  Object.keys(hash).forEach(key => {
    if (hash[key] === 1) {
      ret.push(Number(key));
    }
  })
  return ret;
}

var array = [1,2,3,4,4,5,5];
console.log(nukeDuplications(array));


0
一个稍微更高效的解决方案是循环遍历数组1次,并计算每个值中出现的次数,然后使用.reduce()将它们存储在对象中,然后再使用.filter()循环遍历数组,只返回出现1次的项。
这种方法还将保留数组的顺序,因为它仅使用对象键作为引用 - 它不会迭代它们。

var array = [1,2,3,4,4,5,5];
var valueCounts = array.reduce((result, item) => {
    if (!result[item]) {
        result[item] = 0;
    }
    result[item]++;
    return result;
}, {});
 
var unique = array.filter(function (elem) {
    return !valueCounts[elem] || valueCounts[elem] <= 1;
}); 
 
console.log(unique)


0
另一个选择是使用一个对象来跟踪元素被使用的次数。这将破坏数组顺序,但在非常大的数组上应该更快。

// Both versions destroy array order.

// ES6 version
function nukeDuplications(arr) {
  "use strict";
  const hash = {};
  arr.forEach(el => {
    const qty = hash[el] || 0;
    hash[el] = qty + 1;
  });

  const ret = [];
  Object.keys(hash).forEach(key => {
    if (hash[key] === 1) {
      ret.push(Number(key));
    }
  })
  return ret;
}

// ES5 version
function nukeDuplicationsEs5(arr) {
  "use strict";
  var hash = {};
  for (var i = 0; i < arr.length; i++) {
    var el = arr[i];
    var qty = hash[el] || 0;
    hash[el] = qty + 1;
  };

  var ret = [];
  for (let key in hash) {
    if (hash.hasOwnProperty(key)) {
        if (hash[key] === 1) {
          ret.push(Number(key));
        }
      }
    }
    return ret;
  }


  var array = [1, 2, 3, 4, 4, 5, 5];
  console.log(nukeDuplications(array));

  console.log(nukeDuplicationsEs5(array));


0

你可以使用这个函数:

function isUniqueInArray(array, value) {
  let counter = 0;
  for (let index = 0; index < array.length; index++) {
    if (array[index] === value) {
      counter++;
    }
  }
  if (counter === 0) {
    return null;
  }
  return counter === 1 ? true : false;
}

const array = [1,2,3,4,4,5,5];
let uniqueValues = [];

array.forEach(element => {
  if(isUniqueInArray(array ,element)){
    uniqueValues.push(element);
  }
});

console.log(`the unique values is ${uniqueValues}`);

如果需要的话,您可以从我的包https://www.npmjs.com/package/jotils或直接从bit https://bit.dev/joshk/jotils/is-unique-in-array安装isUniqueInArray函数。

0

我想用我在重新阅读后想出的答案来回答我的问题

const array = [1, 2, 3, 4, 4, 5, 5];
const filtered = array.filter(item => {
  const { length }  = array.filter(currentItem => currentItem === item)
  if (length === 1) {
     return true;
   }
});
console.log(filtered)

一行代码:array.filter(x => array.filter(y => x === y).length === 1) - Tuhin Karmakar

0

这里有很多过于复杂和运行缓慢的代码。以下是我的解决方案:

let numbers = [1,2,3,4,4,4,4,5,5]
let filtered = []

numbers.map((n) => {
    if(numbers.indexOf(n) === numbers.lastIndexOf(n)) // If only 1 instance of n
        filtered.push(n)
})

console.log(filtered)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接