4

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.

  • For first 2 Objects : DS01 = 123, DS02 = 88888, DS06 = 666
  • For last 2 Objects : DS01 = 124, DS02 = 99999, DS06 = 333

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

  • making a single function
  • passing these kinds of array of objects as a parameter
  • and finally getting the reduced dataset

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);

7
  • 1
    You can use reduce for this, but if you don't show the code you wrote so far, we can't make recommendations that let you change it so it does what you want. And on a predictable data type note, having properties be "either a number or an array" means writing more code later on than if you simple ensure it's always an array, with one or more values, and then checking .length later in in your code. Commented Nov 29, 2019 at 17:49
  • 1
    That's not JSON. These are all array of objects. What is the difference between JSON and Object Literal Notation? Commented Nov 29, 2019 at 17:51
  • 1
    do you have always the same count of common keys Commented Nov 29, 2019 at 17:52
  • 1
    @NinaScholz Yes, the group of common keys are same in count. Because these are being formatted from a table with rowspan. Common values are from merged rows. Commented Nov 29, 2019 at 17:55
  • 1
    @Mike'Pomax'Kamermans What I have done so far was totally a mess. That's why I have not added the snippet you are looking for. But one thing I want to discuss is that I have some solutions where key names are defined in the code. But as you can see I have different other data-sets of pretty same structure, That is what making me confused. Commented Nov 29, 2019 at 18:02

1 Answer 1

2

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

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

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.