Сортировка массива объекта с несколькими значениями - PullRequest
1 голос
/ 06 февраля 2020

Привет, у меня есть этот массив:

var array = [{
   "datecrea":"2020-01-31T16:14:46+01:00",
   "datas":{
      "badge":"new",
      "downloads":1,
   },
},
{
   "datecrea":"2020-01-31T17:14:46+01:00",
   "datas":{
      "badge":"soon",
      "downloads":0,
   },
},
{
   "datecrea":"2020-01-31T18:14:46+01:00",
   "datas":{
      "badge":"",
      "downloads":3,
   },
},
{
   "datecrea":"2020-01-31T19:14:46+01:00",
   "datas":{
      "badge":"topten",
      "downloads":5,
   },
},
{
   "datecrea":"2020-01-31T20:14:46+01:00",
   "datas":{
      "badge":"new",
      "downloads":1,
   },
}]

Я хочу отсортировать этот массив, но используя несколько значений, и вот шаги сортировки:

  1. badge
    1. «Скоро» является наиболее важным
    2. «Новый»
    3. «Топтен» является наименее важным
  2. загрузки
  3. datecrea

У меня уже есть этот код, который сортирует по дате, а затем по загрузкам:

            array.sort(function(a,b){
                return new Date(b.datecrea) - new Date(a.datecrea);
            })
            .sort(function(a,b){
                return b.datas.downloads - a.datas.downloads;
            })

Ответы [ 4 ]

2 голосов
/ 06 февраля 2020

Вы можете создать массив строк значков на основе их «важности», а затем иметь функцию .sort, которая сортирует по:

  • разнице в datecrea с. Если ноль, то на
  • разница в downloads. Если ноль, то на
  • Разница в индексе значка в массиве строк значка
const badges = ['soon', 'new', 'topten', ''];
array.sort((a, b) => (
  (badges.indexOf(a.datas.badge) - badges.indexOf(b.datas.badge)) ||
  (new Date(b.datecrea) - new Date(a.datecrea)) ||
  (b.datas.downloads - a.datas.downloads)
));

const badges = ['soon', 'new', 'topten', ''];
var array = [{
   "datecrea":"2020-01-31T16:14:46+01:00",
   "datas":{
      "badge":"new",
      "downloads":1,
   },
},
{
   "datecrea":"2020-01-31T17:14:46+01:00",
   "datas":{
      "badge":"soon",
      "downloads":0,
   },
},
{
   "datecrea":"2020-01-31T18:14:46+01:00",
   "datas":{
      "badge":"",
      "downloads":3,
   },
},
{
   "datecrea":"2020-01-31T19:14:46+01:00",
   "datas":{
      "badge":"topten",
      "downloads":5,
   },
},
{
   "datecrea":"2020-01-31T20:14:46+01:00",
   "datas":{
      "badge":"new",
      "downloads":1,
   },
},
{
   "datecrea":"2020-01-31T20:14:46+01:00",
   "datas":{
      "badge":"",
      "downloads":1,
   },
}]

array.sort((a, b) => (
  (badges.indexOf(a.datas.badge) - badges.indexOf(b.datas.badge)) ||
  (b.datas.downloads - a.datas.downloads) ||
  (new Date(b.datecrea) - new Date(a.datecrea))
));
console.log(array);

Не звоните .sort дважды - звоните только один раз, и поместите все логи c в этот один обратный вызов. Если вы дважды наберете .sort, отсортированные результаты по первому .sort будут потеряны, поскольку массив будет полностью пересортирован по второму .sort.

.
2 голосов
/ 06 февраля 2020

Вам не нужно писать три sort() метода. Вы можете сделать это за один sort().

Примерно так:

var array = [{
    "datecrea": "2020-01-31T16:14:46+01:00",
    "datas": {
      "badge": "new",
      "downloads": 1,
    },
  },
  {
    "datecrea": "2020-01-31T17:14:46+01:00",
    "datas": {
      "badge": "soon",
      "downloads": 0,
    },
  },
  {
    "datecrea": "2020-01-31T18:14:46+01:00",
    "datas": {
      "badge": "",
      "downloads": 3,
    },
  },
  {
    "datecrea": "2020-01-31T19:14:46+01:00",
    "datas": {
      "badge": "topten",
      "downloads": 5,
    },
  },
  {
    "datecrea": "2020-01-31T20:14:46+01:00",
    "datas": {
      "badge": "new",
      "downloads": 1,
    },
  }
]

const badgeWeights = {
  soon: 3,
  new: 2,
  topten: 1,
};

const result = array.sort(function(a, b) {
  if (a.datecrea !== b.datecrea) {
    return new Date(b.datecrea) - new Date(a.datecrea);
  }
  
  if (a.datas.downloads !== b.datas.downloads) {
    return b.datas.downloads - a.datas.downloads;
  }
  
  const aWeight = a.datas.badge ? badgeWeights[a.datas.badge] : 0;
  const bWeight = b.datas.badge ? badgeWeights[b.datas.badge] : 0;
  
  return bWeight - aWeight;
});

console.log(result);
0 голосов
/ 06 февраля 2020

Вы можете использовать Array.sort() с несколькими сравнениями. И вы можете создать объект для хранения рангов значков для использования при сортировке.

var items=[{datecrea:"2020-01-31T16:14:46+01:00",datas:{badge:"new",downloads:1}},{datecrea:"2020-02-12T17:14:46+01:00",datas:{badge:"soon",downloads:0}},{datecrea:"2020-01-28T18:14:46+01:00",datas:{badge:"",downloads:3}},{datecrea:"2020-03-31T19:14:46+01:00",datas:{badge:"topten",downloads:5}},{datecrea:"2020-01-31T20:14:46+01:00",datas:{badge:"new",downloads:3}}];

let badgeRanks = {
  soon: 3,
  new: 2,
  topten: 1

}

items.sort(function(item1, item2) {

  let date1 = new Date(item1.datecrea)
  let date2 = new Date(item2.datecrea)

  if (date1.getTime() > date2.getTime()) return -1;
  if (date1.getTime() < date2.getTime()) return 1;

  if (item1.datas.downloads > item2.datas.downloads) return -1;
  if (item1.datas.downloads < item2.datas.downloads) return 1;

  if (badgeRanks[item1.datas.badge] > badgeRanks[item2.datas.badge]) return -1;
  if (badgeRanks[item1.datas.badge] < badgeRanks[item2.datas.badge]) return 1;


});

console.log(items);
0 голосов
/ 06 февраля 2020

Я имею в виду, это не очень чистый метод выполнения многоуровневой сортировки, но ...

...
.sort(function(a, b) {
   return rankBadge(a) - rankBadge(b);
})

function rankBadge(badge) {
    switch (badge) {
        case "soon": return 3;
        case "new": return 2;
        case "toptem": return 1;
        default: return 0;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...