1

I have an object as:

[
  {
    "DATA": "2016-01-22",
    "TOTAL": "7"
  },
  {
    "DATA": "2016-01-25",
    "TOTAL": "3"
  },
  {
    "DATA": "2016-01-26",
    "TOTAL": "1"
  },
  {
    "DATA": "2016-01-27",
    "TOTAL": "2"
  },
  {
    "DATA": "2016-01-22",
    "TOTAL": "1"
  },
  {
    "DATA": "2016-01-25",
    "TOTAL": "1"
  },
  {
    "DATA": "2016-01-27",
    "TOTAL": "1"
  }, 
 ...
]

How can I shrink it down to something like below, this is, concatenate/join the TOTAL keys where the date is the same and fill with 0 in case the date doesn't repeat?:

[
  {
    "DATA": "2016-01-22",
    "TOTAL": ["7", "1"]
  },
  {
    "DATA": "2016-01-25",
    "TOTAL": ["3", "1"]
  },
  {
    "DATA": "2016-01-26",
    "TOTAL": ["1", "0"]
  },
  {
    "DATA": "2016-01-27",
    "TOTAL": ["2", "1"]
  }
]

I've been trying with this block of code, but can't get TOTAL keys all the same dimension - filled with zeros would be fine.

var output = [];
d.forEach(function(value) {
    var existing = output.filter(function(v, i) {
        return v.DATA == value.DATA;
    });
    if (existing.length) {
        var existingIndex = output.indexOf(existing[0]);
        output[existingIndex].TOTAL = output[existingIndex].TOTAL.concat(value.TOTAL);
    } else {
        if (typeof value.TOTAL == 'string')
            value.TOTAL = [value.TOTAL];
        output.push(value);
    }
});
console.log(JSON.stringify(output, null, 4));
mjpramos
  • 543
  • 5
  • 16
  • `output` appears to return expected result, save for object at index `2` contains an array having `.length` of `1`? – guest271314 Oct 03 '16 at 23:51

2 Answers2

1
var someData = [] // <- your instantiated array in question.
var transformedData = [];

var highestCount = 0;

someData.forEach(x => {
    var foundIndex = transformedData.findIndex((ele) => ele.DATA === x.DATA);
    if (foundIndex < 0) {
        transformedData
            .push({DATA : x.DATA, TOTAL : [x.TOTAL]});
    } else {
        transformedData[foundIndex]
            .TOTAL.push(x.TOTAL);
        var currentCountAtIndex = transformedData[foundIndex].TOTAL.length;
        if (highestCount < transformedData[foundIndex].TOTAL.length) highestCount = currentCountAtIndex;
    }
});

// fill any indicies in array that are lower than the highest count with 0
transformedData
    .forEach(x => {
        if (x.TOTAL.length < highestCount) {
            while(x.TOTAL.length < highestCount) {
                x.TOTAL.push(0);
            }
        }
    });
httpNick
  • 2,524
  • 1
  • 22
  • 34
0

It could be as simple as this:

var result = {};
var test = [
  {
    "DATA": "2016-01-22",
    "TOTAL": "7"
  },
  {
    "DATA": "2016-01-25",
    "TOTAL": "3"
  },
  {
    "DATA": "2016-01-26",
    "TOTAL": "1"
  },
  {
    "DATA": "2016-01-27",
    "TOTAL": "2"
  },
  {
    "DATA": "2016-01-22",
    "TOTAL": "1"
  },
  {
    "DATA": "2016-01-25",
    "TOTAL": "1"
  },
  {
    "DATA": "2016-01-27",
    "TOTAL": "1"
  }];

console.log("test array: ", test);

var len = 0,
sorted;

// Flatten the object.
test.forEach( d => {
   result[d.DATA] == undefined ? result[d.DATA] = [d.TOTAL] : result[d.DATA].push(d.TOTAL);
});

// Sort so we get the max length to know how many zeros to add.
sorted = Object.keys(result).sort( (k, b) => {
   return result[k].length - result[b].length;
});

// Max length from the sorted array. 
len = result[sorted[sorted.length - 1]].length;

// push zeros
Object.keys(result).forEach( k => {
   if(result[k].length < len){
  for(var i = result[k].length; i < len; i++){
     result[k].push("0");
  }
   }
});

console.log("result: ", result);
inoabrian
  • 3,762
  • 1
  • 19
  • 27
  • 1
    Nice answer. If that works, than I'd go with that. The only thing is that you're changing the 'DATA' keys to their values, which may not be what the OP needs (at least it's not what we have on the question's example) – rafaelbiten Oct 04 '16 at 00:10
  • Thanks, it's still really the "same" object. Would just have to change what key you access the values with. I am adding the zeros now. – inoabrian Oct 04 '16 at 00:12