Сравните два массива объектов и добавьте новый атрибут к сопоставляемому объекту

#javascript #arrays #object

#javascript #массивы #объект

Вопрос:

У меня есть два массива объектов, подобных этому:

 let data1 = [ { userid_b: 'dan12345' }, { userid_b: 'emma12345' } ]
let data2 =[ 
  { username: 'dan', userid: 'dan12345' },
  { username: 'johndoe', userid: 'john12345' },
  { username: 'emma', userid: 'emma12345' },
  { username: 'Bob', userid: 'bob12345' },
  { username: 'Sam', userid: 'sam12345' } 
]
  

Я хочу сравнить эти два из userid_b и userid , и если они совпадают, я хочу добавить новый атрибут к data2 .

Итак, я хочу, чтобы результат был таким:

 let data2 =[ 
  { username: 'dan', userid: 'dan12345', newAttribute: true },
  { username: 'johndoe', userid: 'john12345' },
  { username: 'emma', userid: 'emma12345', newAttribute: true },
  { username: 'Bob', userid: 'bob12345' },
  { username: 'Sam', userid: 'sam12345' } 
]
  

Как я могу этого добиться?

Ответ №1:

Зациклите оба массива и сравните значения, выполнив присвоение при необходимости:

 var data1 = [
  { userid_b: 'dan12345' },
  { userid_b: 'emma12345' }
];

var data2 = [ 
  { username: 'dan', userid: 'dan12345' },
  { username: 'johndoe', userid: 'john12345' },
  { username: 'emma', userid: 'emma12345' },
  { username: 'Bob', userid: 'bob12345' },
  { username: 'Sam', userid: 'sam12345' } 
];

// Loop the main array
for (var i = 0; i < data2.length; i  ) {
  // Loop the second array
  for (var j = 0; j < data1.length; j  ) {
    // If the user id matches
    if (data2[i].userid == data1[j].userid_b) {
      // Add the attribute
      data2[i].newAttribute = true;
      // Break out of the the 'j' loop to stop unnecessary iterations
      break;
    }
  }
}

console.log(data2);  

Комментарии:

1. не было бы более эффективным сначала выполнить цикл data ?

2. Да, возможно, вы правы. В любом случае вы заставили меня не забыть добавить разрыв в.

Ответ №2:

Вы можете выполнить обход массива с помощью цикла foreach, см. ниже

 var data1 = [ { userid_b: 'dan12345' }, { userid_b: 'emma12345' } ];
    var data2 =[ 
      { username: 'dan', userid: 'dan12345' },
      { username: 'johndoe', userid: 'john12345' },
      { username: 'emma', userid: 'emma12345' },
      { username: 'Bob', userid: 'bob12345' },
      { username: 'Sam', userid: 'sam12345' } 
    ];

    data1.forEach(function(data1record,index,data1arr){

          data2.forEach(function(data2record,data2idx,data2arr){

                if(data1record.userid_b===data2record.userid){

                    data2record["newAttribute"]=true;
                }

          })
    });

    console.log(data2);
  

Комментарии:

1. Извините, я не понял, не могли бы вы объяснить поподробнее?

2. datarecord2 — это объект, который находился в массиве data2 и имел свойство userid, поэтому ссылался только я. В вопросе задавался вопрос о сравнении на основе идентификатора пользователя..

Ответ №3:

 // Make an array of new users for easy lookup.
const newUsers = data1.map(elt => elt.userid_b);

// Filter data2 down to only matching elements, then add new attribute.
data2.filter(elt => newUsers.contains(elt.username))
  .forEach(elt => elt.newAttribute = true);
  

Ответ №4:

Вы также могли бы сделать что-то подобное этому.

 let data1 = [{
  userid_b: 'dan12345'
}, {
  userid_b: 'emma12345'
}]
let data2 = [{
  username: 'dan',
  userid: 'dan12345'
}, {
  username: 'johndoe',
  userid: 'john12345'
}, {
  username: 'emma',
  userid: 'emma12345'
}, {
  username: 'Bob',
  userid: 'bob12345'
}, {
  username: 'Sam',
  userid: 'sam12345'
}];


var userIds = data1.map(function(obj) {
  return obj.userid_b;
});


var result = data2.map(function(dataObj) {

  if (userIds.includes(dataObj.userid)) {
    dataObj.newAttribute = true;
  }
  return dataObj;
});

console.log(result);  

Ответ №5:

Преобразуйте data1 в new Map() , а затем выполняйте итерацию data2 всякий раз, когда userid находится на карте add newAttribute prop к объекту:

 const data1 = [ { userid_b: 'dan12345' }, { userid_b: 'emma12345' } ]
const data2 =[ 
  { username: 'dan', userid: 'dan12345' },
  { username: 'johndoe', userid: 'john12345' },
  { username: 'emma', userid: 'emma12345' },
  { username: 'Bob', userid: 'bob12345' },
  { username: 'Sam', userid: 'sam12345' } 
];

const usersSet = new Set(data1.map((item) => item.userid_b));

data2.forEach((item) => usersSet.has(item.userid) amp;amp; (item.newAttribute = true));

console.log(data2);  

Комментарии:

1. Почему вы используете Map вместо Set ?

2. Я привык создавать карты объектов, поэтому, естественно, выбираю Map, но вы правы, Set было бы лучше в подобных случаях.

Ответ №6:

С помощью map() и indexOf().

Возьмите имена пользователей (значения) из объектов первого массива:

 var data1_values = data1.map(o => {
    return o.userid_b;
});
  

Результатом является data1_values = ['dan12345', 'emma12345'] .

Теперь пройдемся по объектам data2 с map() помощью. Проверьте с помощью

 data1_values.indexOf(o.userid) > -1 
  

( o является объектом data2 )

если в нем data1_values есть o.userid .

Всего:

 let data1 = [
  { userid_b: 'dan12345' },
  { userid_b: 'emma12345' }
];
let data2 = [
  { username: 'dan', userid: 'dan12345' },
  { username: 'johndoe', userid: 'john12345' },
  { username: 'emma', userid: 'emma12345' },
  { username: 'Bob', userid: 'bob12345' },
  { username: 'Sam', userid: 'sam12345' }
];

var data1_values = data1.map(o => {
  return o.userid_b;
});

data2.map((o, i) => {
  if(data1_values.indexOf(o.userid) > -1) {
    data2[i]["newAttribute"] = true;
  }
});

console.log(data2);