-1

I have "available" data and want to convert it into "desired".

I tried to merge all objects inside array using this but its not working coz as you can see for timestamp = 10 we have 2 values of 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.log(output)

The output was

[
  {
    "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
  }
]

As you can see in the desired output i want 2 objects with timestamp = 10 but in the function output its is overwriting the first one and keeping only one object.

We will get multiple values for same timestamp for only one measurement which is sw_version. For other measurements like temperature or pressure we won't get multiple values for same timestamps. sw_version is optional as well so we may get data where sw_version will not be there and we just have to merge without thinking about duplicating rows timestamp is mandatory it will always be there

7
  • 3
    I think you need to provide more rules as to how exactly merge here. E.g. what happens when you get a second value for pressure or temperature for a timestamp where you already have a measurement? Do you want to handle this the same way as for sw_version i. e. also have a separate object in the output for those? What happens if you receive the same measurement for the same timestamp twice e.g. m1 = { timestamp: 10, temp: 10 } and m2 = { timestamp: 10, temp: 10 }. Should these be one or two objects in the output? Commented Aug 13, 2024 at 17:03
  • 1
    please clarify your question: are the rows with sw_version are always the first in your initial array ? Commented Aug 13, 2024 at 17:05
  • Please clarify your question: is there some final line without timestamp or sw_version properties ? Commented Aug 13, 2024 at 17:10
  • @Mushroomator to answer your first question yes we might get second value for pressure or temperature for a timestamp where we already have a measurement just like sw_version Second question answer is no same measurement for the same timestamp twice will not happen. Hope this answers your question and thanks for asking Commented Aug 13, 2024 at 17:11
  • @MisterJojo Answer to both your question is No. sw_version can appear anywhere. and No row without timestamp is possible. Thanks Commented Aug 13, 2024 at 17:13

2 Answers 2

0

First, I would group by timestamp and store all sw_version in an array. Then, I would create the expected structure for each sw_version for each timestamp. I would use a special case, if there is no 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.log(output);

Sign up to request clarification or add additional context in comments.

Comments

0

it could be done this way :

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.log( JSON.stringify(result,0,2))
.as-console-wrapper { max-height: 100% !important; top: 0; }

4 Comments

it fails if sw_version is not present for example [{ "timestamp": 20, "pressure": 14.22 } { "timestamp": 20, "temperature": 38.50 } ]
@Shaick : I've Asked you for this is there some final line without timestamp or sw_version properties and you'are responded no Why do you change this rule ?
Sorry I was confused with the word 'final'. That's why i said No. I apologize for that. So Timestamp will always be there but sw_version is optional.
@shamikh final line mean any lines on your desired array. and all of them have a timestamp and a sw_version properties. If it is not the case you should edit your question with a really representatives case for input and output arrays, which is not the case actually.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.