Подтвердить что ты не робот

Как проверить, имеет ли массив объектов одинаковые значения свойств?

Мне нужна помощь при повторении через массив, я все время застреваю или изобретаю колесо.

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

Как я могу проверить, есть ли в массиве два (или более) одинакового имени? Мне не нужен счетчик, просто устанавливая переменную, если значения массива не уникальны. Имейте в виду, что длина массива является динамической, а также значениями массива.

4b9b3361

Ответ 1

Используйте array.prototype.map и array.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);

JSFIDDLE.

Ответ 2

ECMA Script 6 Версия

Если вы находитесь в среде, поддерживающей ECMA Script 6 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 возвращает число, основанное на уникальных данных (только добавляет записи, если данные уникальны). Если/когда у вас есть повторяющиеся имена, размер не будет увеличиваться (поскольку данные не будут уникальными), что означает, что мы уже видели текущее имя и оно вернет true.


ECMA Script 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, он не будет обрабатывать остальную часть элементов.

Ответ 3

Попробуйте простой цикл:

var repeat = [], tmp, i = 0;

while(i < values.length){
  repeat.indexOf(tmp = values[i++].name) > -1 ? values.pop(i--) : repeat.push(tmp)
}

Демо

Ответ 4

С Underscore.js Можно сделать несколько способов с помощью Underscore. Вот один из них. Проверка того, что массив уже уникален.

function isNameUnique(values){
    return _.uniq(values, function(v){ return v.name }).length == values.length
}

С ванильным JavaScript Проверяя, нет ли повторяющихся имен в массиве.

function isNameUnique(values){
    var names = values.map(function(v){ return v.name });
    return !names.some(function(v){ 
        return names.filter(function(w){ return w==v }).length>1 
    });
}

Ответ 5

Вы можете использовать map, чтобы вернуть только имя, а затем использовать forEach, чтобы проверить, существует ли он как минимум дважды:

var areAnyDuplicates = false;

values.map(function(obj) {
    return obj.name;
}).forEach(function (element, index, arr) {
    if (arr.indexOf(element) !== index) {
        areAnyDuplicates = true;
    }
});

Fiddle

Ответ 6

Чтобы узнать, есть ли у простого массива дубликаты, мы можем сравнить первые и последние индексы одного и того же значения:

Функция:

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

Ответ 7

если вы ищете логическое значение, самым быстрым способом будет

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)