Pauloo
Pauloo

Reputation: 1

Create Object from Array and sort

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

Upvotes: 0

Views: 61

Answers (3)

RobG
RobG

Reputation: 147503

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

Upvotes: 0

Paul Boutes
Paul Boutes

Reputation: 3305

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.

Upvotes: 0

Andreas
Andreas

Reputation: 21911

// 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}]

Upvotes: 1

Related Questions