Объединить объекты внутри массива объектов с дубликатами

У меня есть «доступные» данные и я хочу преобразовать их в «желаемые».

Я пытался объединить все объекты внутри массива, используя это, но это не работает, потому что, как вы можете видеть, для timestamp = 10 у нас есть 2 значения sw_version.

const available = [
    {
      "timestamp": 10,
      "sw_version": "AA"
    },
    {
      "timestamp": 10,
      "sw_version": "AB"
    },
    {
      "timestamp": 20,
      "sw_version": "QFX-1.2.5 B"
    },
    {
      "timestamp": 10,
      "pressure": 14.75
    },
    {
      "timestamp": 20,
      "pressure": 14.22
    },
    {
      "timestamp": 10,
      "temperature": 15.96
    },
    {
      "timestamp": 20,
      "temperature": 38.50
    },
{
      "timestamp": 30,
      "temperature": 2.2
    },
    {
      "timestamp": 30,
      "pressure": 9.8
    }
  ]

const desired = [
    {
      "timestamp": 10,
      "sw_version": "AA",
      "pressure": 14.75,
      "temperature": 15.96
    },
    {
      "timestamp": 10,
      "sw_version": "AB",
      "pressure": 14.75,
      "temperature": 15.96
    },
    {
      "timestamp": 20,
      "sw_version": "QFX-1.2.5 B",
      "pressure": 14.22,
      "temperature": 38.5
    },
{
      "timestamp": 30,
      "pressure": 9.8,
      "temperature": 2.2
    }
  ]

const output = available.reduce((result, item) => {
      const i = result.findIndex((resultItem) => resultItem.timestamp === item.timestamp);
      if (i === -1) {
        result.push(item);
      } else {
        result[i] = { ...result[i], ...item };
      }
      return result;
    }, []);
    
console.info(output)

Результат был

[
  {
    "timestamp": 10,
    "sw_version": "AB",
    "pressure": 14.75,
    "temperature": 15.96
  },
  {
    "timestamp": 20,
    "sw_version": "QFX-1.2.5 B",
    "pressure": 14.22,
    "temperature": 38.5
  },
  {
    "timestamp": 30,
    "temperature": 2.2,
    "pressure": 9.8
  }
]

Как вы можете видеть в желаемом выводе, мне нужны 2 объекта с меткой времени = 10, но в выводе функции он перезаписывает первый и сохраняет только один объект.

Мы получим несколько значений для одной и той же отметки времени только для одного измерения — sw_version. Для других измерений, таких как температура или давление, мы не получим несколько значений для одних и тех же временных меток. sw_version также является необязательным, поэтому мы можем получить данные, в которых sw_version не будет, и нам просто нужно объединить, не думая о дублировании строк. временная метка обязательна, она всегда будет там

Я думаю, вам нужно предоставить больше правил относительно того, как именно здесь происходит слияние. Например. что происходит, когда вы получаете второе значение для pressure или temperature для отметки времени, для которой у вас уже есть измерение? Хотите ли вы поступить с этим так же, как и с sw_version i. е. также есть отдельный объект на выходе для них? Что произойдет, если вы получите одно и то же измерение для одной и той же временной метки дважды, например. m1 = { timestamp: 10, temp: 10 } и m2 = { timestamp: 10, temp: 10 }. Должны ли это быть один или два объекта на выходе?

Mushroomator 13.08.2024 19:03

пожалуйста, уточните свой вопрос: строки с sw_version всегда являются первыми в исходном массиве?

Mister Jojo 13.08.2024 19:05

Уточните, пожалуйста, ваш вопрос: есть ли финальная строка без свойств timestamp или sw_version?

Mister Jojo 13.08.2024 19:10

@Mushroomator, чтобы ответить на ваш первый вопрос: да, мы можем получить второе значение давления или температуры для метки времени, где у нас уже есть измерение, такое же, как sw_version. Ответ на второй вопрос: нет, одно и то же измерение для одной и той же метки времени дважды не произойдет. Надеюсь, это ответит на ваш вопрос, и спасибо, что спросили.

shamikh 13.08.2024 19:11

@MisterJojo Ответ на оба ваших вопроса: нет. sw_version может появиться где угодно. и ни одна строка без отметки времени невозможна. Спасибо

shamikh 13.08.2024 19:13

Есть еще одна проблема. Учитывая ваши данные, предположим, вы получили еще одно измерение { timestamp: 10, temperature: 420 }. Сколько выходных объектов вы ожидаете для отметки времени 10 или какие здесь должны быть значения для версии программного обеспечения? AA или AB или иметь два объекта для обоих? Проблема здесь будет в том, что чем больше измерений вы получите, тем больше возможных комбинаций значений. На мой взгляд, у вас есть концептуальная проблема со стратегией слияния. Я мог бы представить что-то вроде этого { timestamp: 10, temp: [20, 10], sw_version: ["AA", "BB"] } для работы, но, очевидно, не знаю варианта использования.

Mushroomator 13.08.2024 19:23

@Mushroomator То, на что вы указываете, - очень правильная ситуация, поэтому на данный момент мы можем предположить, что только одно свойство, такое как sw_version, может иметь более 1 значений для одной и той же метки времени. я тоже отредактирую вопрос

shamikh 13.08.2024 19:40
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
7
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

это можно было бы сделать так:

const available = 
  [ { timestamp: 10, sw_version: 'AA'          }
  , { timestamp: 10, sw_version: 'AB'          }
  , { timestamp: 10, pressure:    14.75        } 
  , { timestamp: 20, pressure:    14.22        } 
  , { timestamp: 10, temperature: 15.96        } 
  , { timestamp: 20, temperature: 38.50        } 
  , { timestamp: 20, sw_version: 'QFX-1.2.5 B' } // off order
  , { timestamp: 30, temperature:  2.2         } 
  , { timestamp: 30, pressure:     9.8         } 
  ];

const result = available
  .filter( ({ sw_version }) => !sw_version )
  .reduce( (res, { timestamp, ...props }) =>
  {
  let rows = res.filter( elm => elm.timestamp === timestamp );

  if (!rows.length )
    res.push({timestamp,...props});
  else
    rows.forEach( line => Object.assign(line, props));  
 
  return res;
  }
  , available
     .filter( ({ timestamp:t, sw_version:v }) => !!t && !!v )
     .map( x => Object.assign({},x))
  );  

console.info( JSON.stringify(result,0,2))
.as-console-wrapper { max-height: 100% !important; top: 0; }

это не удается, если sw_version отсутствует, например [{ "timestamp": 20, "pressure": 14.22 } { "timestamp": 20, "temperature": 38.50 } ]

shamikh 13.08.2024 20:02

@Shaick: Я спросил тебя об этом is there some final line without timestamp or sw_version properties и ты ответил no Почему ты меняешь это правило?

Mister Jojo 13.08.2024 20:05

Извините, меня смутило слово «финал». Вот почему я сказал «Нет». Я прошу прощения за это. Таким образом, Timestamp всегда будет присутствовать, но sw_version не является обязательным.

shamikh 13.08.2024 20:12

Последняя строка @samikh означает любые строки в вашем массиве desired. и все они имеют свойства timestamp и sw_version. Если это не так, вам следует отредактировать свой вопрос, указав действительно репрезентативный случай для входных и выходных массивов, что на самом деле не так.

Mister Jojo 13.08.2024 20:20

@samikh Я обновил свой ответ.

Mister Jojo 13.08.2024 20:51
Ответ принят как подходящий

Во-первых, я бы сгруппировал timestamp и сохранил все sw_version в массиве. Затем я бы создал ожидаемую структуру для каждого sw_version для каждого timestamp. Я бы использовал особый случай, если нет sw_version.

const available = [{"timestamp": 10,"sw_version": "AA"},{"timestamp": 10,"sw_version": "AB"},{"timestamp": 20,"sw_version": "QFX-1.2.5 B"},{"timestamp": 10,"pressure": 14.75},{"timestamp": 20,"pressure": 14.22},{"timestamp": 10,"temperature": 15.96},{"timestamp": 20,"temperature": 38.50},{"timestamp": 30,"temperature": 2.2},{"timestamp": 30,"pressure": 9.8}];

const output = Object.entries(available.reduce((acc, el) => {
  if (!(el.timestamp in acc)) acc[el.timestamp] = {};
  if ("sw_version" in el) 
    if (!("sw_version" in acc[el.timestamp])) acc[el.timestamp].sw_version = [el.sw_version];
    else acc[el.timestamp].sw_version.push(el.sw_version);
  else
    acc[el.timestamp] = {...acc[el.timestamp], ...el};
  return acc;
}, {})).flatMap(([timestamp, el]) => !("sw_version" in el)
  ? el
  : el.sw_version.map(sw_version => ({
      ...el,
      sw_version
    }))
);

console.info(output);

Другие вопросы по теме