У меня есть массив объектов JS:

  var a = [{a:"a1",b:"b",c:"c",prop:false},
           {a:"a1",b:"b",c:"c",prop:false},
           {a:"a",b:"b",c:"c",prop:false},
           {a:"a2",b:"b",c:"c",prop:false},
           {a:"a3",b:"b",c:"c",prop:false},
           {a:"a1",b:"b",c:"c",prop:false}];

Я должен найти дубликаты последнего элемента, но БЕЗ рассмотрения ключа prop: когда я нахожу их, соответствующий логический параметр пропуска должен быть установлен в true.

Я сделал самую простую вещь в мире, и она отлично работает, но я бродил, если есть что-то, что может сделать JS (без сторонних библиотек), лучше или в «элегантности», в современности или производительности:

var toTest = a[a.length-1];
for(var i=0;i<a.length;i++){
      if(toTest.a==a[i].a && toTest.b==a[i].b && toTest.c==a[i].c){
         a[i].prop = true;
         a[a.length-1].prop = true;
      }
    }

Любой совет ценится

4
user1094081 29 Авг 2017 в 12:46

4 ответа

Лучший ответ

Вы можете использовать комбинацию Array.forEach и Array.every. Создайте список ключей для тестирования и на каждой итерации проверяйте эти ключи и обновляйте объект.

a[a.length-1].prop = true мне кажется ненужным, поскольку вы не удаляете элемент, поэтому он будет обновлен на последней итерации.

var a = [{a:"a1",b:"b",c:"c",prop:false},
         {a:"a1",b:"b",c:"c",prop:false},
         {a:"a",b:"b",c:"c",prop:false},
         {a:"a2",b:"b",c:"c",prop:false},
         {a:"a3",b:"b",c:"c",prop:false},
         {a:"a1",b:"b",c:"c",prop:false}];
var toTest = a[a.length -1];
var keysToTest = ['a', 'b', 'c'];

a.forEach((o)=>{
  var valid = keysToTest.every((k) => o[k] === toTest[k]);
  if(valid){
    o.prop = true;
  }
});

console.log(a)
1
Rajesh 29 Авг 2017 в 10:00

Вы можете использовать обычный цикл forEach

var a = [{a:"a1",b:"b",c:"c",prop:false}, {a:"a1",b:"b",c:"c",prop:false}, {a:"a",b:"b",c:"c",prop:false}, {a:"a2",b:"b",c:"c",prop:false},{a:"a1",b:"b",c:"c",prop:false},{a:"a1",b:"b",c:"c",prop:false}];     
var toTest = a[a.length-1];              
a.forEach(function(item){
  item.prop = (item.a == toTest.a && item.b == toTest.b && item.c == toTest.c) ? true : false;
});
console.log(a);
1
Batman25663 29 Авг 2017 в 10:13

Используйте Array.filter() с функцией, которая сравнивает только a, b и c.

Изменить: я полностью заменил мой предыдущий ответ. Я думаю, что Array.filter () - это способ поиска дубликатов последней записи в массиве в соответствии с запросом.

1
neuhaus 29 Авг 2017 в 10:07

То, что у вас есть, в значительной степени это. Есть некоторые твики, которые вы можете сделать, но это хорошо, так как за исключением вы хотите остановить на шаг раньше, когда i < a.length - 1 (так как вы не хотите сравнивать последнюю запись с самим собой и устанавливать prop неправильно).

Некоторые настройки, которые вы могли бы сделать:

  • a[a.length-1].prop = true; может быть toTest.prop = true;
  • Вы можете кэшировать a[i] в переменную, а не искать ее каждый раз
  • Вы можете кэшировать a, b и c вместо того, чтобы каждый раз искать их на объекте (но движок JavaScript сделает это, если это все равно имеет значение)
  • В ES2015 + вы можете использовать присвоение деструктуры, чтобы получить a, b и c

Так, например:

// Caching the last item
var last = a[a.length - 1];
// Caching the values to check
var checka = last.a, checkb = last.b, checkc = last.c;
// Stop at i < a.length - 1, caching that to l
for (var i = 0, l = a.length - 1; i < l; ++i) {
    // Cache a[i]
    var entry = a[i];
    if (entry.a == checka && entry.b == checkb && entry.c == checkc) {
        entry.prop = last.prop = true;
    }
}

Live Copy:

var a = [{a:"a1",b:"b",c:"c",prop:false},
           {a:"a1",b:"b",c:"c",prop:false},
           {a:"a",b:"b",c:"c",prop:false},
           {a:"a2",b:"b",c:"c",prop:false},
           {a:"a3",b:"b",c:"c",prop:false},
           {a:"a1",b:"b",c:"c",prop:false}];

// Caching the last item
var last = a[a.length - 1];
// Caching the values to check
var checka = last.a, checkb = last.b, checkc = last.c;
// Stop at i < a.length - 1, caching that to l
for (var i = 0, l = a.length - 1; i < l; ++i) {
    // Cache a[i]
    var entry = a[i];
    if (entry.a == checka && entry.b == checkb && entry.c == checkc) {
        entry.prop = last.prop = true;
    }
}
console.log(a);
.as-console-wrapper {
  max-height: 100% !important;
}

Вот версия ES2015 +, просто для справки:

const last = a[a.length - 1];
const {a: checka, b: checkb, c: checkc} = last;
for (let i = 0, l = a.length - 1; i < l; ++i) {
    const {a: thisa, b: thisb, c: thisc} = a[i];
    if (thisa == checka && thisb == checkb && thisc == checkc) {
        a[i].prop = last.prop = true;
    }
}

Live Copy:

const a = [{a:"a1",b:"b",c:"c",prop:false},
           {a:"a1",b:"b",c:"c",prop:false},
           {a:"a",b:"b",c:"c",prop:false},
           {a:"a2",b:"b",c:"c",prop:false},
           {a:"a3",b:"b",c:"c",prop:false},
           {a:"a1",b:"b",c:"c",prop:false}];

const last = a[a.length - 1];
const {a: checka, b: checkb, c: checkc} = last;
for (let i = 0, l = a.length - 1; i < l; ++i) {
    const {a: thisa, b: thisb, c: thisc} = a[i];
    if (thisa == checka && thisb == checkb && thisc == checkc) {
        a[i].prop = last.prop = true;
    }
}
console.log(a);
.as-console-wrapper {
  max-height: 100% !important;
}

Соответствует ли это любому из ваших критериев, зависит от вас.

1
T.J. Crowder 29 Авг 2017 в 10:02