按年和月排序数组

时间:2021-03-17 21:23:01

I have the array as below,

我有如下数组,

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

I want to sort the array by year first and after that sort month from the year,

我希望按年份排序数组,然后在该年的那个月之后,

I want the output like this,

我想要像这样的输出,

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

How to achieve this?

怎么做到这一点?

7 个解决方案

#1


0  

You can also use lodash library for sorting data by multiple column.

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

I have created a demo on Stackblitz. I hope this will help/guide to you/others.

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

lodash - Documentation

lodash - 文档

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

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

#2


3  

You could take an object for the month names and their numerical value.

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

The chain the order by taking the delta of year and month.

通过取年和月的三角形来连锁订单。

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


1  

You can make a map which maps the Month to the month number and then use Arrays.sort() with your own custom comparator :

您可以创建一个将Month映射到月份数的映射,然后将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


1  

You can create an array for months names and sort like this:

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

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


1  

Since you are ok with using lodash this can be achived by a simple sortBy

既然你可以使用lodash,那么可以通过简单的sortBy来实现

_.sortBy(yearAndMonth, a => new Date(1+ a.month + a.year))

_.sortBy(yearAndMonth,a => new Date(1+ a.month + a.year))

It will construct a new Date for each month and year (with date 1) and that should work the way you want.

它将为每个月和每年(日期1)构建一个新的日期,并且应该按照您想要的方式工作。

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; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Note: You do not need to have array/object/map of all the months for this to have a look up to perform > or <

注意:您不需要拥有所有月份的数组/对象/地图,以便查看执行>或<

#6


0  

Declaring the month names in an array to get the relative value of the month string when comparing with each other.

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

First comparison will be on the year, if both the year values are same then proceeding with the month comparison based on the months array created.

如果两个年份值相同,则首先进行比较,然后根据创建的月份数组继续进行月份比较。

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

#7


0  

See also: JsFiddle

另见:JsFiddle

Allow me to provide a plain ES version (sort array of objects on 1 or more key values, serial dependant (sort on 1, sort 2 within 1, sort on 3 within 1 and 2 etc.), non mutating, i.e. keep the original array as is):

允许我提供一个简单的ES版本(对一个或多个键值排序的对象数组,依赖于序列(排序为1,排序2为1,排序为3,1和2等),非变异,即保留原始数组原样):

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",
    }
  ];
}
<pre></pre>

#1


0  

You can also use lodash library for sorting data by multiple column.

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

I have created a demo on Stackblitz. I hope this will help/guide to you/others.

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

lodash - Documentation

lodash - 文档

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

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

#2


3  

You could take an object for the month names and their numerical value.

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

The chain the order by taking the delta of year and month.

通过取年和月的三角形来连锁订单。

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


1  

You can make a map which maps the Month to the month number and then use Arrays.sort() with your own custom comparator :

您可以创建一个将Month映射到月份数的映射,然后将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


1  

You can create an array for months names and sort like this:

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

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


1  

Since you are ok with using lodash this can be achived by a simple sortBy

既然你可以使用lodash,那么可以通过简单的sortBy来实现

_.sortBy(yearAndMonth, a => new Date(1+ a.month + a.year))

_.sortBy(yearAndMonth,a => new Date(1+ a.month + a.year))

It will construct a new Date for each month and year (with date 1) and that should work the way you want.

它将为每个月和每年(日期1)构建一个新的日期,并且应该按照您想要的方式工作。

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; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Note: You do not need to have array/object/map of all the months for this to have a look up to perform > or <

注意:您不需要拥有所有月份的数组/对象/地图,以便查看执行>或<

#6


0  

Declaring the month names in an array to get the relative value of the month string when comparing with each other.

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

First comparison will be on the year, if both the year values are same then proceeding with the month comparison based on the months array created.

如果两个年份值相同,则首先进行比较,然后根据创建的月份数组继续进行月份比较。

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

#7


0  

See also: JsFiddle

另见:JsFiddle

Allow me to provide a plain ES version (sort array of objects on 1 or more key values, serial dependant (sort on 1, sort 2 within 1, sort on 3 within 1 and 2 etc.), non mutating, i.e. keep the original array as is):

允许我提供一个简单的ES版本(对一个或多个键值排序的对象数组,依赖于序列(排序为1,排序2为1,排序为3,1和2等),非变异,即保留原始数组原样):

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",
    }
  ];
}
<pre></pre>