如何检查对象数组是否具有重复的属性值?

IT技术 javascript arrays unique
2021-01-21 09:59:09

我需要一些帮助来迭代数组,我一直被卡住或重新发明轮子。

values = [
    { name: 'someName1' },
    { name: 'someName2' },
    { name: 'someName1' },
    { name: 'someName1' }
]

如何检查数组中是否有两个(或更多)相同的名称值?我不需要计数器,如果数组值不唯一,只需设置一些变量。请记住,数组长度是动态的,数组值也是如此。

6个回答

使用array.prototype.maparray.prototype.some

var values = [
    { name: 'someName1' },
    { name: 'someName2' },
    { name: 'someName4' },
    { name: 'someName2' }
];

var valueArr = values.map(function(item){ return item.name });
var isDuplicate = valueArr.some(function(item, idx){ 
    return valueArr.indexOf(item) != idx 
});
console.log(isDuplicate);

我将替换返回部分: return valueArr.indexOf(item, idx + 1) !== -1
2021-03-15 09:59:09
@JoelFernando - 答案是在 6 年前及以下写的,有人添加了一个适用于Set. 您的答案将适用于一系列原语。这里的问题是关于一个对象数组,其中内部属性是我们不想复制的对象。
2021-03-19 09:59:09
indexOf 如果数组很大,性能会很差。
2021-03-22 09:59:09
另一种选择是new Set(arr).size !== arr.length检查数组是否有重复项。
2021-03-30 09:59:09

ECMA 脚本 6 版本

如果您处于支持 ECMA Script 6's 的环境中Set,那么您可以使用Array.prototype.some一个Set对象,如下所示

let seen = new Set();
var hasDuplicates = values.some(function(currentObject) {
    return seen.size === seen.add(currentObject.name).size;
});

在这里,我们将每个对象插入name到 中,Set并检查size添加前后是否相同。这是有效的,因为Set.size返回基于唯一数据的数字(如果数据唯一,则 set 仅添加条目)。如果/当你有重复的名字时,大小不会增加(因为数据不是唯一的),这意味着我们已经看到了当前的名字,它会返回 true。


ECMA 脚本 5 版本

如果你没有Set支持,那么你可以使用一个普通的 JavaScript 对象本身,就像这样

var seen = {};
var hasDuplicates = values.some(function(currentObject) {

    if (seen.hasOwnProperty(currentObject.name)) {
        // Current name is already seen
        return true;
    }

    // Current name is being seen for the first time
    return (seen[currentObject.name] = false);
});

一样可以写得简洁,像这样

var seen = {};
var hasDuplicates = values.some(function (currentObject) {
    return seen.hasOwnProperty(currentObject.name)
        || (seen[currentObject.name] = false);
});

注意:在这两种情况下,我们都使用Array.prototype.some因为它会短路。当它从函数中获得一个真值时,它会true立即返回,它不会处理其余的元素。

我如何确保它会处理其余的元素?
2021-03-13 09:59:09
@chovy 问题是:“我如何检查数组中是否有两个(或更多)同名值?我不需要计数器,如果数组值不唯一,只需设置一些变量。” 这与删除重复项无关。我认为这是这里最好的答案!
2021-03-13 09:59:09
@AnnaSmother 如果要处理所有元素,请forEach自己使用和编写逻辑。
2021-03-19 09:59:09
@JoshBeamindexOf将不得不迭代数组以找出元素是否存在,但任何使用散列的东西都会快得多。因此,如果数组非常大,ES5 和 ES6 方式都会快得多。
2021-03-25 09:59:09
有趣的方法,使用hasOwnProperty. 我在您评论的其他一些答案中看到,indexOf在大型阵列中性能不佳。对于较大的对象,您建议的上述 ES5 方式通常对性能更友好吗?
2021-03-27 09:59:09

在 TS 和 ES6 中,您可以创建一个具有唯一属性的新 Set,并将其大小与原始数组进行比较。

const values = [
  { name: 'someName1' },
  { name: 'someName2' },
  { name: 'someName3' },
  { name: 'someName1' }
]

const uniqueValues = new Set(values.map(v => v.name));

if (uniqueValues.size < values.length) {
  console.log('duplicates found')
}

这实际上是最好的答案
2021-03-14 09:59:09

要知道简单数组是否有重复,我们可以比较相同值的第一个最后一个索引:

功能:

var hasDupsSimple = function(array) {

    return array.some(function(value) {                            // .some will break as soon as duplicate found (no need to itterate over all array)
       return array.indexOf(value) !== array.lastIndexOf(value);   // comparing first and last indexes of the same value
    })
}

测试:

hasDupsSimple([1,2,3,4,2,7])
// => true

hasDupsSimple([1,2,3,4,8,7])
// => false

hasDupsSimple([1,"hello",3,"bye","hello",7])
// => true

对于对象数组,我们需要先将对象值转换为简单数组:

使用以下命令将对象数组转换为简单数组map

var hasDupsObjects = function(array) {

  return array.map(function(value) {
    return value.suit + value.rank

  }).some(function(value, index, array) { 
       return array.indexOf(value) !== array.lastIndexOf(value);  
     })
}

测试:

var cardHand = [
  { "suit":"spades", "rank":"ten" },
  { "suit":"diamonds", "rank":"ace" },
  { "suit":"hearts", "rank":"ten" },
  { "suit":"clubs", "rank":"two" },
  { "suit":"spades", "rank":"three" },
]

hasDupsObjects(cardHand);
// => false

var cardHand2 = [
  { "suit":"spades", "rank":"ten" },
  { "suit":"diamonds", "rank":"ace" },
  { "suit":"hearts", "rank":"ten" },
  { "suit":"clubs", "rank":"two" },
  { "suit":"spades", "rank":"ten" },
]

hasDupsObjects(cardHand2);
// => true
@SystemsRebooter,谢谢!!正是我要找的。
2021-04-11 09:59:09
如何找到索引也是最新的重复值
2021-04-12 09:59:09

如果您正在寻找布尔值,最快的方法是

var values = [
    { name: 'someName1' },
    { name: 'someName2' },
    { name: 'someName1' },
    { name: 'someName1' }
]

// solution
var hasDuplicate = false;
values.map(v => v.name).sort().sort((a, b) => {
  if (a === b) hasDuplicate = true
})
console.log('hasDuplicate', hasDuplicate)