【问题标题】:Sort array by year and month [closed]按年和月对数组进行排序[关闭]
【发布时间】:2019-01-25 04:35:24
【问题描述】:

我有如下数组,

let  yearAndMonth  =  [
    { "year": 2013, "month": "FEBRUARY" },
    { "year": 2015, "month": "MARCH" },
    { "year": 2013, "month": "JANUARY" },
    { "year": 2015, "month": "FEBRUARY" }
]

我想先按 year 对数组进行排序,然后再按年份的 month 排序,

我想要这样的输出,

yearAndMonth  =  [
    { "year": 2013, "month": "JANUARY " },
    { "year": 2013, "month": "FEBRUARY" },
    { "year": 2015, "month": "FEBRUARY" },
    { "year": 2015, "month": "MARCH" }
]

如何做到这一点?

【问题讨论】:

  • 这个问题的解决方案不是很简单,但仍然有很多人将此作为与其他人重复发布的内容......愚蠢的事情。终于接受了解决方案,与我合作非常好......谢谢大家的帮助

标签: javascript arrays angular sorting lodash


【解决方案1】:

您还可以使用lodash 库按多列对数据进行排序。

我在 Stackblitz 上创建了一个演示。我希望这会对您/其他人有所帮助/指导。

lodash - Documentation

组件.html

<table width="100%">
  <tr>
    <td>Year</td>
    <td>Month</td>
  </tr>
  <tr *ngFor="let datas of sortedData">
    <td>{{datas.year}}</td>
    <td>{{datas.month}}</td>
  </tr>
</table>

组件.ts

 sortedData: any[];
  data = [
    { "year": 2013, "month": "FEBRUARY" },
    { "year": 2015, "month": "MARCH" },
    { "year": 2013, "month": "JANUARY" },
    { "year": 2013, "month": "MARCH" },
    { "year": 2013, "month": "APRIL" },
    { "year": 2015, "month": "FEBRUARY" }
  ];

monthArray: any = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
        "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];

  ngOnInit() {
    this.sortedData = _.orderBy(data, [(datas) => datas.year, (user) => (this.monthArray.indexOf(user.month))], ["asc", "asc"]);
    console.log(this.sortedData);
  }

【讨论】:

  • 感谢您提供 lodash 库的解决方案。
  • 与其导入整个库来执行排序等基本操作,不如尝试Vanilla JS:data.sort(function(a,b) {return (a.year - b.year) || (monthArray.indexOf(a.month) - monthArray.indexOf(b.month));})
  • @NiettheDarkAbsol 我同意这有点矫枉过正,但如果他已经将该库用于其他目的,_.orderBy() 也很简单。
【解决方案2】:

您可以为月份名称及其数值取一个对象。

通过年和月的增量来链接订单。

var array =  [{ year: 2013, month: "FEBRUARY" }, { year: 2015, month: "MARCH" }, { year: 2013, month: "JANUARY" }, { year: 2015, month: "FEBRUARY" }];

array.sort(function (a, b) {
    var MONTH = { JANUARY: 0, FEBRUARY: 1, MARCH: 2, APRIL: 3, MAY: 4, JUNE: 5, JULY: 6, AUGUST: 7, SEPTEMBER: 8, OCTOBER: 9, NOVEMBER: 10, DECEMBER: 11 };
    return a.year - b.year || MONTH[a.month] - MONTH[b.month];
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案3】:

    您可以制作一张将月份映射到月份编号的地图,然后将Arrays.sort() 与您自己的自定义比较器一起使用:

    let months = { 'JANUARY' : 1, 'FEBRUARY' : 2, 'MARCH' : 3, 'APRIL' : 4, 'MAY' : 5, 'JUNE' : 6, 'JULY' : 7, 'AUGUST' : 8, 'SEPTEMBER' : 9, 'OCTOBER' : 10, 'NOVEMBER' : 11, 'DECEMBER' : 12 };
    let  yearAndMonth  =  [ { "year": 2013, "month": "FEBRUARY" }, { "year": 2015, "month": "MARCH" }, { "year": 2013, "month": "JANUARY" }, { "year": 2015, "month": "FEBRUARY" } ];
    
    yearAndMonth.sort((a,b)=> a.year - b.year || months[a.month.toUpperCase()] - months[b.month.toUpperCase()]);
    
    console.log(yearAndMonth);

    【讨论】:

      【解决方案4】:

      您可以为月份名称创建一个数组并按如下方式排序:

      let data = [
        { "year": 2013, "month": "FEBRUARY" }, { "year": 2015, "month": "MARCH" },
        { "year": 2013, "month": "JANUARY" }, { "year": 2015, "month": "FEBRUARY" }
      ];
      
      let months = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
                    "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
      
      data.sort(
       (a, b) => (a.year - b.year) || (months.indexOf(a.month) - months.indexOf(b.month))
      );
      
      
      console.log(data);
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      【讨论】:

        【解决方案5】:

        在数组中声明月份名称以获取月份字符串相互比较时的相对值。

        第一次比较将在年份上进行,如果两个年份值相同,则根据创建的月份数组继续进行月份比较。

        let months = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
                  "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
        
        
        
        yearAndMonth.sort((a,b) =>{
            if(a.year > b.year) return 1;
            else if(a.year <  b.year) return -1;
            else {
                if(months.indexOf(a.month.toUpperCase()) > 
                   months.indexOf(b.month.toUpperCase()))
                       return 1;
                else if(months.indexOf(a.month.toUpperCase()) < 
                 months.indexOf(b.month.toUpperCase())) 
                       return -1
                else return 0;
          }
        });
        

        【讨论】:

          【解决方案6】:

          由于您可以使用lodash,这可以通过简单的sortBy 来实现

          _.sortBy(yearAndMonth, a =&gt; new Date(1+ a.month + a.year))

          它将为每个月和年(日期为 1)构造一个 new Date,这应该可以按照您想要的方式工作。

          let  yearAndMonth  =  [
              { "year": 2013, "month": "FEBRUARY" },
              { "year": 2015, "month": "MARCH" },
              { "year": 2013, "month": "JANUARY" },
              { "year": 2015, "month": "FEBRUARY" }
          ]
          
          let res = _.sortBy(yearAndMonth, a => new Date(1 + a.month + a.year));
          console.log('Sorted Result: ', res);
          .as-console-wrapper { max-height: 100% !important; top: 0; }
          &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"&gt;&lt;/script&gt;

          注意:您不需要所有月份的 array/object/map 来查找执行 &gt;&lt;

          【讨论】:

          • 当我在 Angular 中使用您的解决方案时,我得到了“'any[]' 类型的参数不可分配给'string' 类型的参数”这个错误。
          • @AniketAvhad 要么使用 [1, a.month, a.year].join('') 要么只使用 + 运算符而不使用数组,我已经进行了相应的编辑,您在编译时遇到了类型检查的问题。
          • 谢谢,现在您的解决方案工作正常。
          • 我相信这应该被提升为最佳答案,因为这将有助于社区和人们访问这个问题!
          【解决方案7】:

          另请参阅:JsFiddle

          请允许我提供一个简单的 ES 版本(对 1 个或多个键值的对象数组进行排序,依赖于序列(按 1 排序,在 1 中排序 2,在 1 和 2 中按 3 排序等),非变异,即保持原数组不变):

          const log = (...str) => 
            document.querySelector("pre").textContent += `${str.join("\n")}\n`;
          const data = getData();
          const xSort = XSort();
          const months = [ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
              "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ];
          
          log( JSON.stringify(
              xSort
              .create(data)
              .orderBy( {key: "year"}, { key: v => months.indexOf(v.month) } ),
              null,
              " ")
            );
          
          function XSort() {
            const multiSorter = sortKeys => {
              if (!sortKeys || sortKeys[0].constructor !== Object) {
                throw new TypeError("Provide at least one {key: [keyname]} to sort on");
              }
              return function (val0, val1) {
                for (let sortKey of sortKeys) {
                  const v0 = sortKey.key instanceof Function ? sortKey.key(val0) : val0[sortKey.key];
                  const v1 = sortKey.key instanceof Function ? sortKey.key(val1) : val1[sortKey.key];
                  const isString = v0.constructor === String || v1.constructor === String;
                  const compare = sortKey.descending ?
                    isString ? v1.toLowerCase().localeCompare(v0.toLowerCase()) : v1 - v0 :
                    isString ? v0.toLowerCase().localeCompare(v1.toLowerCase()) : v0 - v1;
                  if (compare !== 0) {
                    return compare;
                  }
                }
              };
            }
            const Sorter = function (array) {
              this.array = array;
            };
          
            Sorter.prototype = {
              orderBy: function(...sortOns) {
                return this.array.slice().sort(multiSorter(sortOns));
              },
            };
          
            return {
              create: array => new Sorter(array)
            };
          }
          
          function getData() {
            return [{
                "year": 2013,
                "month": "FEBRUARY",
              },
              {
                "year": 2015,
                "month": "MARCH",
              },
              {
                "year": 2015,
                "month": "SEPTEMBER",
              },
              {
                "year": 2013,
                "month": "JANUARY",
              },
              {
                "year": 2013,
                "month": "MARCH",
              },
              {
                "year": 2013,
                "month": "APRIL",
              },
              {
                "year": 2015,
                "month": "FEBRUARY",
              }
            ];
          }
          &lt;pre&gt;&lt;/pre&gt;

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-12
            • 2017-12-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多