Сравнить значения двух объектов с помощью вложенных циклов for и вернуть массив измененных объектов

#javascript #arrays #object #if-statement #assign

#javascript #массивы #объект #if-оператор #назначить

Вопрос:

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

 const testArr1 = [
      {
        event: "Ryan's birthday",
        time: "4:00",
      },
      {
        event: "Steves's birthday",
        time: "2:00",
      },
      {
        event: "Helen's birthday",
        time: "1:00",
      },
      {
        event: "Paola's birthday",
        time: "3:00",
      },
      {
        event: "Jared's birthday",
        time: "9:00",
      },
    ];
  

и

 const testArr2 = [
      {
        time: "4:00",
        temp: 41,
      },
      {
        time: "6:00",
        temp: 42,
      },
      {
        time: "8:00",
        temp: 43,
      },
      {
        time: "1:00",
        temp: 44,
      },
      {
        time: "3:00",
        temp: 45,
      },
      {
        time: "9:00",
        temp: 46,
      },
    ];
  

Я хотел бы создать функцию, которая принимает эти два массива объектов и возвращает новый массив объектов с именем dataToDisplay . dataToDisplay должны содержать объекты, связанные с событиями.

Я хочу, чтобы функция getDataToDisplay видела, есть ли у события доступные данные о температуре, сравнивая testArr1 и testArr2 значения в time ключе, а затем предоставила мне массив объектов, которые либо имеют соответствующие temp данные, когда time значения совпадают, либо no matching data found отметили, когда time значения не совпадают.

Моя проблема заключается в том, что, используя такую функцию, как я его построил теперь, объект продавливают, чтобы dataToDisplay в каждой итерации возвращает false при сравнении значений времени, так что есть много повторяющихся данных.

Вот функция:

 const getDataToDisplay = (testArr1, testArr2) => {
  const dataToDisplay = [];

  for (let i = 0; i < testArr1.length; i  ) {
    for (let j = 0; j < testArr2.length; j  ) {
      let objToPush = {};

      //if times in both objects are equal, push an object containing event, time, and temp value at that time to dataToDisplay
      //break and move on if times are equal
      if (testArr1[i].time === testArr2[j].time) {
        Object.assign(objToPush, {
          event: testArr1[i].event,
          time: testArr1[i].time,
          temp: testArr2[j].temp,
        });
        dataToDisplay.push(objToPush);
        break;
      } else {
        //if times in both objects are NOT equal, push an object containing event, time, and a temp value of "no matching data found"
        Object.assign(objToPush, {
          event: testArr1[i].event,
          time: testArr1[i].time,
          temp: "no matching data found",
        });
        //this is pushing an object every time the condition returns false
        //I only want one object returned if false
        dataToDisplay.push(objToPush);
      }
    }
  }
  return dataToDisplay;
};
  

вот что происходит при вызове функции

 console.log(getDataToDisplay(testArr1, testArr2));
    //logs
    //     [
    //   {
    //     "event": "Ryan's birthday",
    //     "time": "4:00",
    //     "temperature": 41
    //   },
    //   {
    //     "event": "Steves's birthday",
    //     "time": "2:00",
    //     "temperature": "no matching data found"
    //   },
    //   {
    //     "event": "Steves's birthday",
    //     "time": "2:00",
    //     "temperature": "no matching data found"
    //   },
    //   {
    //     "event": "Steves's birthday",
    //     "time": "2:00",
    //     "temperature": "no matching data found"
    //   }
    //   ...
    // ]

    //but I want it to log something like this
    // [
    //   {
    //     event: "Ryan's birthday",
    //     time: "4:00",
    //     temperature: 41,
    //   },
    //   {
    //     event: "Steves's birthday",
    //     time: "2:00",
    //     temperature: "no matching data found",
    //   },
    //   {
    //     event: "Helen's birthday",
    //     time: "1:00",
    //     temperature: 44,
    //   },
    //   ...
    // ];
  

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

Ответ №1:

Вы могли бы взять объект для всех времен temparatures массива и сопоставить events массив со значениями times объекта, используя time в качестве ключа.

 const
    noData = 'no matching data found',
    events = [{ event: "Ryan's birthday", time: "4:00" }, { event: "Steves's birthday", time: "2:00" }, { event: "Helen's birthday", time: "1:00" }, { event: "Paola's birthday", time: "3:00" }, { event: "Jared's birthday", time: "9:00" }],
    temperatures = [{ time: "4:00", temp: 41 }, { time: "6:00", temp: 42 }, { time: "8:00", temp: 43 }, { time: "1:00", temp: 44 }, { time: "3:00", temp: 45 }, { time: "9:00", temp: 46 }],
    times = Object.fromEntries(temperatures.map(({ time, temp }) => [time, temp])),
    result = events.map(o => ({ ...o, temperature: times[o.time] || noData }));

console.log(result);  
 .as-console-wrapper { max-height: 100% !important; top: 0; }  

Ответ №2:

Вы можете использовать Array.prototype.reduce и просмотреть каждый объект в testArr1 и найти объект с совпадением temp в testArr2 с помощью Array.prototype.find . При совпадении объедините оба, чтобы заполнить «не найдено совпадающих записей»:

 const testArr1 = [{ event: "Ryan's birthday", time: "4:00" }, { event: "Steves's birthday", time: "2:00" }, { event: "Helen's birthday", time: "1:00" }, { event: "Paola's birthday", time: "3:00" }, { event: "Jared's birthday", time: "9:00" }],
testArr2 = [{ time: "4:00", temp: 41 }, { time: "6:00", temp: 42 }, { time: "8:00", temp: 43 }, { time: "1:00", temp: 44 }, { time: "3:00", temp: 45 }, { time: "9:00", temp: 46 }];

const getDataToDisplay = (testArr1, testArr2) => {
  const defaultText =  "no matching records found";
  return testArr1.reduce((acc, p) => {
    const matchingTime = testArr2.find(t => t.time === p.time);
    const temperature = (matchingTime amp;amp; matchingTime.temp) || defaultText;
    acc.push({...p, temperature});
    return acc;
  }, []);
}
console.log(getDataToDisplay(testArr1, testArr2));  

Проблема с вашим подходом заключается в том, что вы сравниваете объект из внешнего цикла for с каждым объектом во внутреннем цикле for. Вам нужно только найти объект, который имеет то же время во втором массиве testArr2 если не найден, добавьте сообщение «не найдено совпадающих записей».

Но в вашем случае внутренний цикл помещает новый объект в выходной массив каждый раз, когда происходит несоответствие со time свойством.