0

i've got an Array like this

(1)  var values = [2014.02.01", "2014.03.01", "2014.03.01", "2014.03.01", "2014.03.01", "2014.03.17", "2014.04.01", "2014.04.01", "2014.04.09",...];

and i want to count the dates and create a object in that format

(2) count = {01.02.2014: 1, 01.03.2014: 4, 17.03.2014: 1, 01.04.2014: 2, 09.04.2014: 1,...}

i tried it in that way but this don't sort the object in the wright way

(3) values.forEach(function(i) { count[i] = (count[i]||0)+1;  });

the result isn't sorted...is there a way to create a object with sorted dates? I already sort the array before creating the object but it doesn't work

edit:

reversing dates is no problem

for (var j=0; j<values.length; j++){
    values[j] = values[j].split(".").reverse().join(".");
}

but creating the object that is sorted by date is the problem...my way (3) doesn't sort the object

Pauloo
  • 1
  • 1
  • duplicate of http://stackoverflow.com/questions/10123953/sort-javascript-object-array-by-date – Psylogic Aug 28 '15 at 12:32
  • As far as I understand you have three problems: change the date format, count the repeated objects in the first array, sort the final array. Did you solve any of the three? –  Aug 28 '15 at 12:32
  • 3
    Your count object is an object, so by definition, it can't be sorted – Finrod Aug 28 '15 at 12:34
  • 1
    Objects don't guarantee order. Although they do appear to be in order, it depends on the browser and the behavior is different in every browser. – Joseph Aug 28 '15 at 12:34
  • you want to sort by count of dates?? – Muhammad Usman Aug 28 '15 at 12:40
  • Are you amenable to using libraries? –  Aug 28 '15 at 12:40
  • 1
    @JosephtheDreamer—ECMAScript 2015 [*OwnPropertyKeys* internal method](http://ecma-international.org/ecma-262/6.0/index.html#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys) makes order explicit and predictable, though in practice it's not reliable as not all implementations in use are compliant yet. – RobG Aug 28 '15 at 13:18

3 Answers3

1
// group the data by date and count the appearances
var grouped = values.reduce(function(l, r) {
    l[r] = (l[r] || 0) + 1;
    return l;
}, {});

// as objects can't be sorted, map it to an array of objects with the desired data as properties
var groupedAndSorted = Object.keys(grouped).map(function(key) {
    return { "date": key, "count": grouped[key] };
}).sort(function(a, b) {
    return a.date > b.date;
});

// [{"date":"2014.02.01","count":1},{"date":"2014.03.01","count":4},{"date":"2014.03.17","count":1},{"date":"2014.04.01","count":2},{"date":"2014.04.09","count":1}]
Andreas
  • 19,756
  • 7
  • 41
  • 49
0

You can do it by following the functional way which tends to be more sexy, shorter. To handle this, you can simulate an hashmap key/value.

You can use Array.prototype.reduce() which is a powerful method.

//Reduce our data and initialize our result to an empty object
//Sort values input and perform reduce
var count = values.sort().reduce(function(result, current){
  //Format our key
  var key = current.split('.').reverse('').join('.');
  //Set value to our object
  result[key] = (++result[key] || 1);
  return result;
}, {});


console.log(count);

EDIT

I've had key formatting for out object.

Paul Boutes
  • 3,181
  • 2
  • 15
  • 21
0

You should sort the dates using a compare function that simply strips the periods before rearranging them:

    var arr = ["2014.02.01", "2014.03.01", "2014.03.01", "2014.03.01", "2014.03.01", "2014.03.17", "2014.04.01", "2014.04.01", "2014.04.09"]

    arr.sort(function(a, b) {
      return (a.replace('.','') - b.replace('.',''));
    }).forEach(function(v,i){arr[i] = v.split('.').reverse().join(".")});

    document.write(arr.join('<br>'));

All thats required next is to turn the array into an object with a count of the recurring dates, which can also reverse the values in each string:

arr = arr.sort(function(a, b) {
      return (a.replace('.','') - b.replace('.',''));
    }).reduce(function(obj, v){
      v = v.split('.').reverse().join('.')
      if (!obj.hasOwnProperty(v)) {
        obj[v] = 0;
      }
      ++obj[v];
      return obj;
    },{});

But be warned, there is no guarantee that you'll get consistent ordering. In the latest version of the language specification, order is based firstly on numeric order if the property is a number, then the order properties are added. The Safari console thinks the keys are numbers so returns the following order:

Object { 01.02.2014: 1, 01.03.2014: 4, 01.04.2014: 2, 09.04.2014: 1, 17.03.2014: 1 }

but when stringified with JSON.stringify or the keys are returned by Object.keys, they're in the same order as Firefox and Chrome which return:

Object { 01.02.2014: 1, 01.03.2014: 4, 17.03.2014: 1, 01.04.2014: 2, 09.04.2014: 1 }

which is consistent with ECMAScript 2015.

To get consistent ordering, you should use ISO 8601 like dates similar to the original but without the periods. But best of all, you should not expect the order to be consistent or predictable, because it across browsers in use (unless you restrict yourself to one particular implementation that does what you want).

RobG
  • 124,520
  • 28
  • 153
  • 188