按JavaScript中的季度年度数据对对象数组进行排序

时间:2016-08-24 04:19:52

标签: javascript arrays json sorting

我有一个包含以下对象的数据数组

[  
   {  
      "name":"Q1'2016",
      "y":0
   },
   {  
      "name":"Q2'2016",
      "y":0
   },
   {  
      "name":"Q3'2016",
      "y":0
   },
   {  
      "name":"Q4'2015",
      "y":0
   }
]

我想根据季度对它们进行排序,因此Q4' 2015应该先行,然后是Q1&2016;等等。

如何实现这一目标?

3 个答案:

答案 0 :(得分:1)

您可以使用sort方法并根据谓词对其进行回调以对对象进行排序;在您的情况下,您要检查包含您的四分之一年信息的对象的名称属性。由于您可能拥有不同季度和年份的数据,因此您需要将季度映射到月份值,以便将它们转换为年/月日期并以这种方式进行比较。

var data = [{
  "name": "Q1'2016",
  "y": 0
}, {
  "name": "Q2'2016",
  "y": 0
}, {
  "name": "Q3'2016",
  "y": 0
}, {
  "name": "Q4'2015",
  "y": 0
}];

var quarterToMonthMap = {
  "Q1": 0,
  "Q2": 3,
  "Q3": 6,
  "Q4": 9
}

function sortByQuarterYear(lhs, rhs) {
  var lhsQuarterYear = lhs.name.split("'");
  var rhsQuarterYear = rhs.name.split("'");
  var lhsDate = new Date(lhsQuarterYear[1], quarterToMonthMap[lhsQuarterYear[0]]);
  var rhsDate = new Date(rhsQuarterYear[1], quarterToMonthMap[rhsQuarterYear[0]]);
  return lhsDate.getTime() - rhsDate.getTime();
}

document.write(JSON.stringify(data.sort(sortByQuarterYear)));

答案 1 :(得分:1)

要按年份和季度排序,您可以使用以下ES6代码段(您可以使用ES5执行完全相同的操作,但我喜欢编写ES6)

input.map((obj, index) => obj.name.split("'").reverse().concat(index)).sort().map(arr => input[arr[2]]);

让我们稍微分解一下

input.map((obj, index) => obj.name.split("'").reverse().concat(index))
  

map()方法创建一个新数组,其结果是在此数组中的每个元素上调用提供的函数   <子> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

我们的“提供的函数”用'字符拆分每个对象的“name”属性,反转生成的数组,并将当前索引添加到结果数组中。

这会产生一个如下所示的数组:

[
    ["2016", "Q1", 0], 
    ["2016", "Q2", 1], 
    ["2016", "Q3", 2], 
    ["2015", "Q4", 3]
]

然后我们拨打.sort

  

sort()方法对数组中的元素进行排序并返回数组。排序不一定稳定。默认排序顺序是根据字符串Unicode代码点   <子> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

然后我们最终得到一个这样的数组:

[
    ["2015", "Q4", 3], 
    ["2016", "Q1", 0], 
    ["2016", "Q2", 1], 
    ["2016", "Q3", 2]
]

所以我们现在有一个附录,注意我们扔在那里的索引没有按顺序排列。我们可以利用这种缺乏秩序来创造秩序。

我们所要做的就是再次调用map,这次返回与我们临时数组中存储的索引相关的原始对象。

.map(arr => input[arr[2]]);

当我们将它们放在一起并调用它时,我们最终得到一个这样的数组:

[
    {
        name: "Q4'2015",
        y: 0
    }, {
        name: "Q1'2016",
        y: 0
    }, {
        name: "Q2'2016",
        y: 0
    }, {
        name: "Q3'2016",
        y: 0
    }
]

这是一个演示:

let input = [  
   {  
      "name":"Q1'2016",
      "y":0
   },
   {  
      "name":"Q2'2016",
      "y":0
   },
   {  
      "name":"Q3'2016",
      "y":0
   },
   {  
      "name":"Q4'2015",
      "y":0
   }
];
    
input = input.map((obj, index) => obj.name.split("'").reverse().concat(index)).sort().map(arr => input[arr[2]]);

console.log(input);

在ES5中做同样的事情:

input.map(function(obj, index){
    return obj.name.split("'").reverse().concat(index);
}).sort().map(function(arr){
    return input[arr[2]];
});

答案 2 :(得分:0)

.sort()与比较器功能结合使用,您可以轻松地将每个值从"Q1'2016"重新格式化为"2016Q1",从而允许进行简单的字母数字比较,因为"2016Q1" > "2015Q4"

function sortQuarters(arr) {
  function reformat(v) {
    return v.replace(/(Q\d)'(\d{4})/, "$2$1");
  }
  return arr.sort(function(a, b) {
    return reformat(a.name).localeCompare(reformat(b.name));
  });
}

console.log(sortQuarters([  
   { "name":"Q1'2016", "y":0 },
   { "name":"Q3'2016", "y":0 },
   { "name":"Q2'2016", "y":0 },
   { "name":"Q4'2015", "y":0 }
]));

(请注意,我所说的重新格式化仅在排序时使用的临时变量中,它不会更改数组中的值。另请注意,我显示的函数会修改传递给的数组的顺序。它并返回相同的数组,它不会创建一个新数组。)