-1

My JSON data be like:

{
  "Data":
    [
      {"ID": A1,"Function": A,"Status": 1},
      {"ID": A1,"Function": B,"Status": 0},
      {"ID": A1,"Function": C,"Status": 1},
      {"ID": A2,"Function": A,"Status": 0},
      {"ID": A2,"Function": B,"Status": 0},
      {"ID": A2,"Function": C,"Status": 2},
      {"ID": A3,"Function": A,"Status": 0},
      {"ID": A3,"Function": B,"Status": 0}
    ]
}

This is what I want:

{
  "Data":
    [
      {"ID": A1,"Status": 1},
      {"ID": A2,"Status": 2},
      {"ID": A3,"Status": 0}
    ]
}

I have so many duplicate IDs while I only need one ID with a maximum of Status. I just don't know where to start with. Could anyone give me some tips?

cyt
  • 68
  • 8

2 Answers2

1

You could use a Map as reference to the index of the result array with the same ID and check if the actual Status is smaller, then update the array.

var data = [{ ID: 'A1', Status: 1 }, { ID: 'A1', Status: 0 }, { ID: 'A1', Status: 1 }, { ID: 'A2', Status: 0 }, { ID: 'A2', Status: 0 }, { ID: 'A2', Status: 2 }, { ID: 'A3', Status: 0 }, { ID: 'A3', Status: 0 }],
    map = new Map,
    filtered = [];

data.forEach(function (o) {
    var index = map.get(o.ID);               // get index
    if (index === undefined) {               // if no index available
        map.set(o.ID, filtered.push(o) - 1); // push object and store index in map
        return;                              // exit early
    }
    if (filtered[index].Status < o.Status) { // check status
        filtered[index] = o;                 // update array
    }
});

console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Without Map

var data = [{ ID: 'A1', Status: 1 }, { ID: 'A1', Status: 0 }, { ID: 'A1', Status: 1 }, { ID: 'A2', Status: 0 }, { ID: 'A2', Status: 0 }, { ID: 'A2', Status: 2 }, { ID: 'A3', Status: 0 }, { ID: 'A3', Status: 0 }],
    filtered = data.reduce(function (r, o) {
        var index = r.findIndex(({ ID }) => ID === o.ID);
        if (index === -1) {
            r.push(o);
            return r;
        }
        if (r[index].Status < o.Status) {
            r[index] = o;
        }
        return r;
    }, []);

console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thank you for helping me, It does work! Could you tell me what `filtered.push(o) - 1` means? Why `-1`? (Sorry I'm a newbie) – cyt Feb 07 '18 at 01:42
  • never mind to ask. `push` returns the new length of the array and for getting the index, you need to subtract one because indices are zero based. – Nina Scholz Feb 07 '18 at 07:08
1

You can use array#reduce and create an object with ID and Status and replace the value of Status if the value is less than the stored value. Extract out all the values from the object using Object#values().

var data = { "Data": [ {"ID": "A1","Function": "A","Status": 1}, {"ID": "A1","Function": "B","Status": 0}, {"ID": "A1","Function": "C","Status": 1}, {"ID": "A2","Function": "A","Status": 0}, {"ID": "A2","Function": "B","Status": 0}, {"ID": "A2","Function": "C","Status": 2}, {"ID": "A3","Function":"A","Status": 0}, {"ID": "A3","Function": "B","Status": 0} ] },
    result = Object.values(data.Data.reduce((r,{ID, Status}) => {
      if(ID in r ) {
        if (r[ID].Status < Status)
          r[ID].Status = Status;
      } else {
        r[ID] = {ID, Status};
      }
      return r;
    },{}));
var output = {Data: result};
console.log(output);
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51