Сравнение двух массивов и заполнение недостающих значений

#javascript #arrays #for-loop

#javascript #массивы #for-цикл

Вопрос:

Я хочу сравнить даты из 2 массивов и вставить имя из соответствующей даты в новый массив. А затем нажмите «0» для пропущенных дат.

Это то, что я пробовал

 var data = [{
  name: 'Amy',
  date: '2020-01-01'
}, {
  name: 'John',
  date: '2020-01-02'
}, {
  name: 'Sara',
  date: '2020-01-04'
}];

var fulldate = ['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04', '2020-01-05'];
var newData = [];
var len = data.length;
for (var i = 0; i < len; i  ) {
  if (data[i].date == fulldate[i]) {
    newData.push(data[i].name);
  } else if (data[i].date != fulldate[i]) {
    newData.push("0")
  }
}

console.log(newData);  

Проблема в том, что он останавливается после обнаружения несоответствующей даты:

 Amy,John,0
  

Это то, что мне нужно

 Amy, John, 0, Sara, 0
  

Ответ №1:

Лучший подход — всегда использовать map и filter . Используйте функцию map для fulldate obj отфильтровывания объекта (если он присутствует) с той же датой, что и текущее el значение. Я использовал тернарный оператор в операторе return, который возвращает name, если объект присутствует, и 0 в противном случае.

 var data = [{
  name: 'Amy',
  date: '2020-01-01'
}, {
  name: 'John',
  date: '2020-01-02'
}, {
  name: 'Sara',
  date: '2020-01-04'
}];

var fulldate = ['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04', '2020-01-05'];


var result = fulldate.map((el) => {
  let obj = data.filter(item => (item.date == el))  
  return (obj[0]) ? obj[0].name : 0;
})

console.log(result);  

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

1. Спасибо вам за это! Это помогает и намного проще. Я должен больше узнать о map и filter

Ответ №2:

  • В вашем коде вы использовали for-loop на основе data переменной длины, но результат имеет ту же длину, fulldate поэтому он будет зацикливаться на fulldate переменной длине.
  • Внутри цикла вы сравнили fulldate[i] == data[i].date , поэтому сравнивали только один и тот же индекс. Внутри цикла вам нужно использовать другой цикл, чтобы найти индекс совпадающей даты.

Вместо использования for цикла вы можете просто сделать это с помощью Array.prototype.map функции. (Внутри функции map, используя Array.prototype.findIndex , вы можете найти соответствующий индекс даты.)

 var data = [{
  name: 'Amy',
  date: '2020-01-01'
}, {
  name: 'John',
  date: '2020-01-02'
}, {
  name: 'Sara',
  date: '2020-01-04'
}];

var fulldate = ['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04', '2020-01-05'];

const result = fulldate.map((date) => {
  const existed = data.findIndex(item => item.date === date);
  return existed >= 0 ? data[existed].name : 0
});
console.log(result);  

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

1. найденный индекс используется для возврата name .

2. Извините. Пропустил это. В этом случае, .find . Вы уже зацикливаетесь, просто получите объект вместо этого. const {name} = data.find(item => item.date === date); return name || '0'

Ответ №3:

 var data = [{
  name: 'Amy',
  date: '2020-01-01'
}, {
  name: 'John',
  date: '2020-01-02'
}, {
  name: 'Sara',
  date: '2020-01-04'
}];
var fulldate = [
  '2020-01-01',
  '2020-01-02',
  '2020-01-03',
  '2020-01-04',
  '2020-01-05'
];
var newData = [];
for(var i = 0; i < fulldate.length; i  ) {
  var found = false;
  for(var k in data) {
    if(data[k].date == fulldate[i]) {
      newData.push(data[k].name);
      found = true;
      break;
    }
  }
  if(!found)
    newData.push("0");
}
console.log(newData);  

Ответ №4:

Предположим, что массивы уже упорядочены по дате, используйте переменную dataIdx для итерации data и Array.map() упрощения цикла for .

 var data = [{name:'Amy', date:'2020-01-01'}, {name:'John', date:'2020-01-02'}, {name:'Sara', date:'2020-01-04'}];

var fulldate = ['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04', '2020-01-05'];

var dataIdx = 0;
var newData = fulldate.map(date => data[dataIdx] amp;amp; data[dataIdx].date == date ? data[dataIdx  ].name : '0');
console.log(newData);  

Ответ №5:

для объявления переменной используйте ‘let’ или ‘const’ вместо var. причина: var vs let vs const

И результат, который вы ищете, можно получить с помощью map amp; find js func.

 const fulldate = ["2020-01-01", "2020-01-02", "2020-01-03", "2020-01-04", "2020-01-05"];
const data = [
 {name: "Amy", date: "2020-01-01"},
 {name: "John", date: "2020-01-02"},
 {name: "Sara", date: "2020-01-04"}
];

const result = fulldate.map(date => {
    const matchingDate = data.find(nameDateObj => nameDateObj['date'] === date);
    return matchingDate ? matchingDate['name'] : 0;
});

console.log(result)  

к вашему сведению: это также можно сделать с помощью findIndex вместо find .

 fulldate.map(date => {
     const matchingDateIndex = data.findIndex(nameDateObj => nameDateObj['date'] === date);
     return matchingDateIndex > -1 ? data[matchingDateIndex]['name'] : 0; 
});
  

Ответ №6:

Для кратчайшего решения вы должны объединить map и find. Вот oneliner:

 const data = [{
  name: 'Amy',
  date: '2020-01-01'
}, {
  name: 'John',
  date: '2020-01-02'
}, {
  name: 'Sara',
  date: '2020-01-04'
}];

const fulldate = ['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04', '2020-01-05'];

const result = fulldate.map(x => (data.find(y => y.date === x) || {name: 0}).name)

console.log(result)