【问题标题】:Sort array of objects by quarterly-yearly data in JavaScript [closed]在JavaScript中按季度数据对对象数组进行排序[关闭]
【发布时间】:2016-08-24 04:19:52
【问题描述】:

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

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

我想按季度对它们进行排序,所以 Q4'2015 应该排在第一位,然后是 Q1'2016,依此类推。

如何实现?

【问题讨论】:

    标签: javascript arrays json sorting


    【解决方案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)));

    【讨论】:

    • 您可以将if/else if/else 替换为return lhsDate.getTime() - rhsDate.getTime();。
    • 好点。谢谢!
    【解决方案2】:

    要按年份和季度排序,您可以使用以下 ES6 sn-p(您可以使用 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

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

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

    [
        ["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]];
    });
    

    【讨论】:

      【解决方案3】:

      将.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 }
      ]));

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-23
        • 2021-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-06
        相关资源
        最近更新 更多