skip to Main Content

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
    }
]

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

2

Answers


  1. it could be done this way :

    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        } 
      ];
    
    const result = available.reduce( (res, { timestamp, sw_version, ...props }) =>
      {
      if ( !!sw_version )
        {
        res.push( { timestamp, sw_version  });
        }
      else
        {
        res.filter( elm => elm.timestamp === timestamp )
           .forEach( line => Object.assign(line, props));  
        }
      return res;
      }
      ,[]);
    
    console.log( JSON.stringify(result,0,2))
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    Or, in case of bad Order:

    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' } // on last...
      ];
    
    const result = available
      .reduce( (res, { timestamp, sw_version, ...props }) =>
      {
      if ( !sw_version )
        {
        res.filter( elm => elm.timestamp === timestamp)
           .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; }
    Login or Signup to reply.
  2. 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);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search