2

I'm searching a powerful solution in TypeScript or JavaScript to count occurrences in an array of object. I'd like to do that by Date. (I need it to create some charts)

For example, i have this array :

var arr = [
    {date: Wed Jan 20 2016 
        type: "Apples"}, 
    {date: Mon Feb 29 2016
        type: "Peaches"},
    {date: Thu Mar 31 2016 
        type: "Apples"},
    {date: Fri Apr 22 2016 
        type: "Apples"},
    {date: Fri Apr 22 2016 
        type: "Apples"},
    {date: Fri Apr 22 2016 
        type: "Apples"},
    {date: Fri Apr 22 2016 
        type: "Strawberries"}
]

The result I would like to have is the next one :

var arr2 = [
        {date: Wed Jan 20 2016 
            type: ["Apples", 1]}, 
        {date: Mon Feb 29 2016
            type: ["Peaches",1]},
        {date: Thu Mar 31 2016 
            type: ["Apples",1]},
        {date: Fri Apr 22 2016 
            type: ["Apples",3],["Strawberries",1]}
    ]

I don't know why, but I can't find a good solution, I'm working on it during some days...

If anybody knows a trick, a function, or something else?

Vincent
  • 33
  • 5
  • 1
    Show the code you've already attempted. – Andy Apr 25 '16 at 12:04
  • something like this : function getOccurences(table) { var tableCount = []; table.sort(); var current = null; var cnt = 0; for (var i = 0; i < table.length; i++) { if (table[i] != current) { if (cnt > 0) { tableCount.push([current, cnt]); } current = table[i]; cnt = 1; } else { cnt++; } } if (cnt > 0) { tableCount.push([current, cnt]); } return tableCount; } – Vincent Apr 25 '16 at 12:41

4 Answers4

2

should work like this:

var x = new Date().getTime(),
    filtered = arr.filter( function (obj) { return obj.date.getTime() >= x }),
    occurenceCount = filtered.length;

I use getTime() to convert the dates to integer, since I had odd behaviour comparing Date objects bevor. arr2 would contain all dates after x (in this exampale NOW) and count would return the number of elements contained in arr2.

Fonzy
  • 691
  • 3
  • 14
2

try this

First create a map

var map = {}; arr.forEach(function(val){
  map[val.date] = map[val.date] || {};
  map[val.date][val.type] = map[val.date][val.type] || 0;
  map[val.date][val.type]++;
});

Now get the output

var output = Object.keys(map).map(function(key){
  var tmpArr = [];
  for(var type in map[key])
  {
     tmpArr.push( [ type, map[key][type] ] )
  }
  return { date : key, type: tmpArr  };
})

DEMO

var arr = [
    {date: "Wed Jan 20 2016",
        type: "Apples"}, 
    {date: "Mon Feb 29 2016",
        type: "Peaches"},
    {date: "Thu Mar 31 2016",
        type: "Apples"},
    {date: "Fri Apr 22 2016" ,
        type: "Apples"},
    {date: "Fri Apr 22 2016" ,
        type: "Apples"},
    {date: "Fri Apr 22 2016" ,
        type: "Apples"},
    {date: "Fri Apr 22 2016" ,
        type: "Strawberries"}
]


    var map = {}; arr.forEach(function(val){
      map[val.date] = map[val.date] || {};
      map[val.date][val.type] = map[val.date][val.type] || 0;
      map[val.date][val.type]++;
    });


    var output = Object.keys(map).map(function(key){
      var tmpArr = [];
      for(var type in map[key])
      {
         tmpArr.push( [ type, map[key][type] ] )
      }
      return { date : key, type: tmpArr  };
    })

    document.body.innerHTML += JSON.stringify(output,0,4);
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
1

With a proper date format like here with ISO date, and a temporary object, you could use a Array#forEach loop and return the wanted result. It works in a single loop.

var array = [{ date: '2016-01-20', type: "Apples" }, { date: '2016-02-29', type: "Peaches" }, { date: '2016-03-31', type: "Apples" }, { date: '2016-04-22', type: "Apples" }, { date: '2016-04-22', type: "Apples" }, { date: '2016-04-22', type: "Apples" }, { date: '2016-04-22', type: "Strawberries" }],
    grouped = [];

array.forEach(function (a) {
    var key = a.date + '|' + a.type;
    if (!this[a.date]) {                
        this[a.date] = { date: a.date, type: [] };;
        grouped.push(this[a.date]);
    }            
    if (!this[key]) {
        this[key] = [a.type, 0];
        this[a.date].type.push(this[key]);
    }
    this[key][1]++;
}, Object.create(null));

document.write('<pre>' + JSON.stringify(grouped, 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
-2

Filter the array and check the date in the filter function.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

function findItemsByDate(value) {
    // find if an item already exists with the date index
    var dateIndex = arr2.findIndex(findDateIndex);
    // create an array or use the existing one based on result
    if(dateIndex === -1){
      var dateArray = []
    }else{
      dateArray = arr2[dateIndex];
    }
    // find the type object based on the input type and add to it, or create a new one.
    if(dateArray.type.hasOwnProperty(value.type)){
       dateArray.type[value.type] += 1;
    }else{
      dateArray.type[value.type] = 1;
    }
}
// utility function to see if an item already exists in the new array with the key for the date.
function findDateIndex(item, index, arr){
        if(item.date = "Thu Mar 31 2016"){
            alert("Has Data")
        return index;
    }
    return -1;
  }

This will return a slightly different, but more managable result than you are looking for.

var arr2 = [
        {date: "Wed Jan 20 2016", type: ["Apples", 1]}, 
        {date: "Mon Feb 29 2016",type: ["Peaches",1]},
        {date: "Thu Mar 31 2016", type: ["Apples",1]},
        {date: "Fri Apr 22 2016", type: {"Apples":3,"Strawberries":1}}
    ]
Aaron Franco
  • 1,560
  • 1
  • 14
  • 19