从数组创建对象并排序

时间:2015-08-28 12:28:55

标签: javascript arrays sorting object

我有一个像这样的数组

(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",...];

我希望计算日期并以该格式创建对象

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

我以这种方式尝试过,但这不会以怀特的方式对象进行排序

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

结果没有排序...有没有办法创建一个带有排序日期的对象?我已经在创建对象之前对数组进行了排序,但它不起作用

编辑:

倒车日期没问题

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

但是创建按日期排序的对象是问题...我的方式(3)不对对象进行排序

3 个答案:

答案 0 :(得分: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}]

答案 1 :(得分:0)

你可以按照功能方式来做到这一点,它往往更性感,更短。要处理此问题,您可以模拟 hashmap键/值

您可以使用Array.prototype.reduce(),这是一种强大的方法。

//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);

修改

我已经输出了对象的密钥格式。

答案 2 :(得分:0)

您应该使用比较函数对日期进行排序,该函数在重新排列之前简单地删除句点:

&#13;
&#13;
    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>'));
&#13;
&#13;
&#13;

接下来需要的是将数组转换为具有重复日期计数的对象,这也可以反转每个字符串中的值:

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;
    },{});

但请注意,无法保证您能获得一致的订购。在最新版本的语言规范中,如果属性是数字,则订单首先基于数字顺序,然后添加订单属性。 Safari控制台认为密钥是数字,因此返回以下顺序:

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

但是当用 JSON.stringify 进行字符串化或者 Object.keys 返回键时,它们的返回顺序与Firefox和Chrome的顺序相同:

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

与ECMAScript 2015一致。

要获得一致的排序,您应该使用类似于原始日期但没有句点的ISO 8601日期。但最重要的是,您不应期望订单是一致的或可预测的,因为它在所使用的浏览器中(除非您将自己局限于一个能够满足您需求的特定实现)。