1

If I have an array of objects and there are certain objects that have the same name/property (in my case there are 2 instances of objects with a name of "highway"), how can I remove these objects from the array and add a new object with that contains data from both?

const data = [
    { "data": [ { "x": "sensor_error_code", "y": [ 0, 9 ] } ], "name": 123 },
    { "data": [ { "x": "road_type", "y": [ 15, 24 ] } ], "name": "city" },
    { "data": [ { "x": "road_type", "y": [ 0, 14 ] } ], "name": "highway" },
    { "data": [ { "x": "road_type", "y": [ 25, 30 ] } ], "name": "highway" },
    { "data": [ { "x": "weather", "y": [ 0, 8 ] } ], "name": "rain" },
    { "data": [ { "x": "weather", "y": [ 9, 24 ] } ], "name": "sun" },
    { "data": [ { "x": "special_object", "y": [ 5, 15 ] } ], "name": true }
];

e.g. having one instance of "highway" with a data object containing the values from both:

{ "data": [ { "x": "road_type", "y": [ 0, 14 ] }, { "x": "road_type", "y": [ 25, 30 ] } ], "name": "highway" }

So far I've tried to make a new empty object and loop over the data array, accumulating that empty object with names and values from that array. I was planning on converting that object to an array in the end. The code I've used is below:

const myData = {};
atts.forEach(att => {
  if (myData[att.name]) {
    myData[att.name].push(att.data)
  } else {
    myData[att.name] = att.data;
  }
})
console.log(myData)

However, the code I've used above involves some additional manipulation to make the data ready for consumption by a library and I was wondering if there are simpler ways to achieve my goal?

3 Answers 3

1

Your solution has a decent start. There are only 2 problems with your solution:

  • You need to "unwrap" the array when pushing it
  • You need to combine them all together at the end
const myData = {};
atts.forEach(att => {
  if (myData[att.name]) {
    myData[att.name].push(...att.data) // Notice this change
  } else {
    myData[att.name] = att.data;
    // or if you don't want to alter the original data
    myData[att.name] = [...att.data]; // basically a shallow copy
  }
})
const result = [];
for (const key in myData) {
    result.push({ data: myData[key], name: key });
}
console.log(result);
Sign up to request clarification or add additional context in comments.

Comments

1

You can use .reduce() (to convert your array into an aggregated value) along with .findIndex() (this helps in finding if data from same category exists in the new array you are making)

const atts = [
    { "data": [ { "x": "sensor_error_code", "y": [ 0, 9 ] } ], "name": 123 },
    { "data": [ { "x": "road_type", "y": [ 15, 24 ] } ], "name": "city" },
    { "data": [ { "x": "road_type", "y": [ 0, 14 ] } ], "name": "highway" },
    { "data": [ { "x": "road_type", "y": [ 25, 30 ] } ], "name": "highway" },
    { "data": [ { "x": "weather", "y": [ 0, 8 ] } ], "name": "rain" },
    { "data": [ { "x": "weather", "y": [ 9, 24 ] } ], "name": "sun" },
    { "data": [ { "x": "special_object", "y": [ 5, 15 ] } ], "name": true }
];


let myData = atts.reduce((agg, x) => {
  let isIndex = agg.findIndex(a => a.name == x.name);
  if(isIndex > -1) agg[isIndex].data.push(x.data[0]);
else {
agg.push({data : x.data , name : x.name});
}
return agg;
},[]);
console.log(myData)

Comments

1

A different approach using reduce - tracking the items by keys and merging the arrays of duplicate objects

const combined = Object.entries(data.reduce((b,a) => {
 // our result will be an object so wrap it in Object.entries so we can iterate through to finish
    if (b.hasOwnProperty(a.name)) b[a.name].data = [...b[a.name].data, ...a.data];
    // if the property exists, merge the 'y' array
    else b[a.name]=a;
    // otherwise add to the object
    return b;
    },{})).map(e => e[1])
    // finally map the result out to the desired format

const data = [
    { "data": [ { "x": "sensor_error_code", "y": [ 0, 9 ] } ], "name": 123 },
    { "data": [ { "x": "road_type", "y": [ 15, 24 ] } ], "name": "city" },
    { "data": [ { "x": "road_type", "y": [ 0, 14 ] } ], "name": "highway" },
    { "data": [ { "x": "road_type", "y": [ 25, 30 ] } ], "name": "highway" },
    { "data": [ { "x": "weather", "y": [ 0, 8 ] } ], "name": "rain" },
    { "data": [ { "x": "weather", "y": [ 9, 24 ] } ], "name": "sun" },
    { "data": [ { "x": "special_object", "y": [ 5, 15 ] } ], "name": true }
];

const combined = Object.entries(data.reduce((b,a) => {
if (b.hasOwnProperty(a.name)) b[a.name].data[0].y = [...b[a.name].data[0].y, ...a.data[0].y];
else b[a.name]=a;
return b;
},{})).map(e => e[1])

console.log(combined)

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.