0

folks, I faced with a problem. I have a huge array with objects. And I need to transform it into a specific array with merging inner properties.

I have a source array

const srcArr = [
  {
    "id": 2142,
    "time": 1579111185330,
    "rpm": 0,
    "speed": 0,
  },
  {
    "id": 435345,
    "time": 1579111186340,
    "rpm": 1,
    "speed": 2,
  },
  {
    "id": 34636,
    "time": 1579111187340,
    "rpm": 2,
    "speed": 4,
  }];

And I need on output array like this, excluding key 'id'.

const outArr = [
  {
    title: "time",
    data: [1579111185330, 1579111186340, 1579111187340]
  },
  {
   title: "rpm",
   data: [0, 1, 2],
  },
  {
   title: "speed",
   data: [0, 2, 4]
  }
]

What should I use? Reduce? map?

5
  • are there only those 3 keys or there could be more than those? Commented Jul 31, 2020 at 10:33
  • no, actually there are about 10 keys and one of them is redundant Commented Jul 31, 2020 at 10:48
  • so none of the answers are what you are looking for? can you please post the real input? Commented Jul 31, 2020 at 10:49
  • 1
    there is no need to provide more input, you just need a function which supports any number of keys Commented Jul 31, 2020 at 10:54
  • I edited my question a little. So now you see there is a kye that should not past in output array. But how many properties I thin it really doesn't matter. Nikita Madeev's answer is most close and almost exactly what I looked for. Commented Jul 31, 2020 at 10:56

4 Answers 4

2

An implementation that works with any number of keys

const srcArr = [
    { time: 1579111185330, rpm: 0, speed: 0, other: 'test1' },
    { time: 1579111186340, rpm: 1, speed: 2, other: 'test2' },
    { time: 1579111187340, rpm: 2, speed: 4, other: 'test3' },
];

const result = srcArr.reduce(
    (acc, obj) =>
        Object.entries(obj).reduce(
            (a, [key, val]) => ({
                ...a,
                [key]: a[key] ? [...a[key], val] : [val],
            }),
            acc,
        ),
    {},
);

console.log(Object.entries(result).map(([title, data]) => ({ title, data })));

With exclude keys:

const srcArr = [
    { id: 1, time: 1579111185330, rpm: 0, speed: 0, other: 'test1' },
    { id: 2, time: 1579111186340, rpm: 1, speed: 2, other: 'test2' },
    { id: 3, time: 1579111187340, rpm: 2, speed: 4, other: 'test3' },
];
const excludeKeys = ['id', 'other'];

const result = srcArr.reduce(
    (acc, obj) =>
        Object.entries(obj)
            .filter(e => !excludeKeys.includes(e[0]))
            .reduce(
                (a, [key, val]) => ({
                    ...a,
                    [key]: a[key] ? [...a[key], val] : [val],
                }),
                acc,
            ),
    {},
);

console.log(Object.entries(result).map(([title, data]) => ({ title, data })));

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

1 Comment

Thank you, Nikita, but could I ask you please to edit your answer, for adding a check on key fields? for example, I want to check if key !== 'id'.
1

You could loop through the array and inside loop through the keys of the object. Use a group object to map each key with the object needed in the output

const srcArr=[{id:2142,time:1579111185330,rpm:0,speed:0,},{id:435345,time:1579111186340,rpm:1,speed:2,},{id:34636,time:1579111187340,rpm:2,speed:4,}];
const group = {}

for(const { id, ...rest } of srcArr) {
  for(const key in rest) {
    group[key] = group[key] || { title: key, data: [] };
    group[key].data.push(rest[key]);
  }
}

console.log(Object.values(group))

Comments

0

You can use reduce with custom initialValue as

[
  {
    title: 'time',
    data: []
  }, {
    title: 'rpm',
    data: []
  }, {
    title: 'speed',
    data: []
  }
]

const srcArr = [
  {
    "time": 1579111185330,
    "rpm": 0,
    "speed": 0,
  },
  {
    "time": 1579111186340,
    "rpm": 1,
    "speed": 2,
  },
  {
    "time": 1579111187340,
    "rpm": 2,
    "speed": 4,
  }];

const result = srcArr.reduce((acc, rec) => {
  return [ 
    ...acc, 
      acc[0].data.push(rec.time),
      acc[1].data.push(rec.rpm),
      acc[2].data.push(rec.speed),
  ]
},[
  {
    title: 'time',
    data: []
  }, {
    title: 'rpm',
    data: []
  }, {
    title: 'speed',
    data: []
  }]).slice(0, 3)

console.log(JSON.stringify(result))

1 Comment

it is bad to assume there are only 3 keys. Even if that was true, better to create a functionality that supports more keys in case this changed in the future.
0

function transformData(array) {
  const destinationObject = {};

  function mergeObjects(destination, source) {
    for (let key in source) {
      const value = source[key];
      if (Array.isArray(destination[key])) {
        destination[key].push(value);
      } else {
        destination[key] = [value];
      }
    }
  }

  function makeTitledArrayFromObject(object) {
    const result = [];
    for (let key in object) {
      result.push({
        title: key,
        data: object[key]
      });
    }
    return result;
  }
  
   array.forEach(mergeObjects.bind(null, destinationObject));
   return makeTitledArrayFromObject(destinationObject);
}

const srcArr = [{ "time": 1579111185330,"rpm": 0,"speed": 0,},{"time":1579111186340,"rpm": 1,"speed": 2,},{"time": 1579111187340,"rpm": 2,"speed": 4}];

const result = transformData(srcArr);
console.log(result);

Comments

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.