Shunjid Rahman
Shunjid Rahman

Reputation: 419

How to reduce array of objects based on common key values?

Let's say, I have an Array of object which looks like:

  var jsonData = [
  {"DS01":123,"DS02":88888,"DS03":1,"DS04":2,"DS05":3,"DS06":666},
  {"DS01":123,"DS02":88888,"DS03":2,"DS04":3,"DS05":4,"DS06":666},

  {"DS01":124,"DS02":99999,"DS03":3,"DS04":4,"DS05":5,"DS06":333},
  {"DS01":124,"DS02":99999,"DS03":5,"DS04":6,"DS05":7,"DS06":333}
];

You can see there are some common key fields which are DS01, DS02 and DS06. Firstly, I want to find which are common group of keys.

I want to convert this array of objects to a format like this:

    var jsonDataReduced = 
     [{
            "DS01": 123,
            "DS02": 88888,
            "DS03": [1, 2],
            "DS04": [2, 3],
            "DS05": [3, 4],
            "DS06": 666
        },
    
        {
            "DS01": 124,
            "DS02": 99999,
            "DS03": [3, 5],
            "DS04": [4, 6],
            "DS05": [5, 7],
            "DS06": 333
        }
    ];

Let's say, I have another array of objects.

var jsonData2 = [{
    "Mass": 3,
    "Force": 3.1,
    "Acceleration": 4
}, {
    "Mass": 3,
    "Force": 4.1,
    "Acceleration": 4
}];

So after reducing it should be:

var jsonData2 = [{
    "Mass": 3,
    "Force": [3.1, 4.1],
    "Acceleration": 4
}];

I have been trying to do these by using Array.reduce() but not getting an idea on how to do this job efficiently.

Is it possible to

What I have tried :

var jsonData2 = [{
        "Mass": 3,
        "Force": 3.1,
        "Acceleration": 4
    }, {
        "Mass": 3,
        "Force": 4.1,
        "Acceleration": 4
    }];

const reduced = jsonData2.reduce((r, e, i, a) => {
  if (i % 2 == 0) {
    const next = a[i + 1];
    const obj = { ...e, Force: [e.Force] }
    if (next) obj.Force.push(next.Force);
    r.push(obj)
  }
  return r;
}, []);

console.log(reduced);

Upvotes: 4

Views: 358

Answers (1)

Nina Scholz
Nina Scholz

Reputation: 386654

You could get common keys and group by them.

var data = [{ DS01: 123, DS02: 88888, DS03: 1, DS04: 2, DS05: 3, DS06: 666 }, { DS01: 123, DS02: 88888, DS03: 2, DS04: 3, DS05: 4, DS06: 666 }, { DS01: 124, DS02: 99999, DS03: 3, DS04: 4, DS05: 5, DS06: 333 }, { DS01: 124, DS02: 99999, DS03: 5, DS04: 6, DS05: 7, DS06: 333 }],
    common,
    temp = data.reduce((r, o, i) => {
        Object.entries(o).forEach(([k, v]) => {
            r[k] = r[k] || [];
            r[k][i] = v;
        });
        return r;
    }, {}),
    min = Infinity,
    result;


Object.entries(temp).forEach(([k, a]) => {
    var s = new Set;
    temp[k] = a.map(v => s.add(v).size);
    min = Math.min(min, s.size);
});

common = Object.keys(temp).filter(k => temp[k][temp[k].length - 1] === min);


result = data.reduce((r, o) => {
    var temp = r.find(q => common.every(k => q[k] === o[k]));
    if (!temp) {
        r.push({ ...o });
    } else {
        Object.keys(o).filter(k => !common.includes(k)).forEach(k => Array.isArray(temp[k]) ? temp[k].push(o[k]) : (temp[k] = [temp[k], o[k]]));
    }
    return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Related Questions