使用lodash检查数组中是否有重复值

35

大家认为使用lodash工具编写一个函数来检查数组中是否有重复值的最佳方法是什么(最佳可解释为最易读或最高效,由您选择)。

我想输入['foo', 'foo', 'bar']并使函数返回true。输入['foo', 'bar', 'baz']并使函数返回false

6个回答

69

你可以尝试这段代码:

function hasDuplicates(a) {
  return _.uniq(a).length !== a.length; 
}

var a = [1,2,1,3,4,5];
var b = [1,2,3,4,5,6];

document.write(hasDuplicates(a), ',',hasDuplicates(b));
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.1.0/lodash.min.js"></script>


=====有什么特别的原因吗? - nackjicholson
1
在这种特定情况下,这并不重要。我已经改成了===。谢谢! - agershun
1
当然可以,但是要挑剔一点,OP要求的是hasDuplicates函数,而不是hasNoDuplicates - user663031
1
改为 hasDuplicates() - agershun
Short and accurate. Great - SUDARSHAN BHALERAO

19

从ES6开始,您可以简单地使用Set,因此代码变成了:

let hasDuplicates = arr => new Set(arr).size != arr.length

console.log(hasDuplicates([5,3,2,1,2,1,2,1]))
console.log(hasDuplicates([1,2,3,4,5]))

这在某种程度上抵消了在这种情况下使用lodash的作用。


7

您可以检查数组中是否存在_.some元素,该元素在数组中查找时不返回自己的位置。换句话说,至少有一个元素在数组中有一个先前的匹配项。

function hasDuplicates(array) {
    return _.some(array, function(elt, index) { 
        return array.indexOf(elt) !== index; 
    });
}

也许这比使用_.uniq的解决方案更快,因为它可以立即识别第一个重复的元素,而无需计算整个唯一化数组。
或者,根据您的编码风格和可读性的要求,如果您想使用ES6箭头函数来简洁地表达:
var earlierMatch  = (elt, index, array) => array.indexOf(elt) !== index;
var hasDuplicates = array => _.some(array, earlierMatch);

indexOf 的使用非常棒!! - Hrishi
吹毛求疵:在“some”(O(n))中使用“indexOf”(O(n))-> O(n2)。 - tokland
2
是的,这是一个O(n^2)用于检查重复项的算法。我不认为这是挑剔,更像是一个重大缺陷。 - Kaleo Brandt

3

嗯,有一个方法可以用,就是 lodash 的 _.uniq() 函数。这个函数会返回一个只包含唯一值的新数组,所以检查数组长度是否改变可以得到你需要返回的真或假值。


2
我不了解lodash,但我提交以下内容:
_.any(_.countBy(['foo', 'foo', 'bar']), function(x){ return x > 1; });

目前为止提出的所有解决方案的问题在于,即使从数组的前两个元素中就可以得出答案,整个输入数组也需要进行处理才能得到答案。

从lodash的版本4开始,_.any已被废弃,推荐使用_.some - random_user_name

0

不需要使用 lodash,可以使用以下代码替代:

function getDuplicates(array, key) {
  return array.filter(e1=>{
    if(array.filter(e2=>{
      return e1[key] === e2[key];
    }).length > 1) {
      return e1;
    }
  })
}

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