Каков наиболее эффективный способ сортировки вложенного json по двум полям?

Образец данных:

[{  'ID': objectID(dcdj12), 
    'Deprt': 'IT',
    'Employees': [ { 'ID': 3, 'StrtDT': '24-12-2022T08:30', 'flag': true },          
                   { 'ID': 2, 'StrtDT': '14-11-2021T08:30'  'flag': true },
                   { 'ID': 1, 'StrtDT': '22-11-2020T08:30', 'flag': false }]
  },
  { 'ID': objectID(dcdj132),
    'Deprt': 'HR',
    'Employees': [ { 'ID': 33, 'StrtDT': '24-12-2022T08:30', 'flag': false},          
                   { 'ID': 22, 'StrtDT': '14-11-2021T08:30'  'flag': true },
                   { 'ID': 11, 'StrtDT': '22-11-2020T08:30', 'flag': false }]
  },
  {  'ID': objectID(dcdj1321),'Deprt' : 'AC', 'Employees': []}... more thn 1000 ]

HTML-код для отображения в таблице:

<tbody>
   <ng-container *ngFor = "let D of Deprt">
     <tr *ngFor = "let Emp of D.Employees" class = "card-text">
       <td> {{D.Deprt}} </td>
       <td> {{Emp.ID}}   </td>
       <td> {{Emp.StrtDT}}  </td>
       <td> {{Emp.flag}}  </td>
    </tr>
   </ng-container>
</tbody>

Текущий выход:

Deprt      ID        StrtDT        flag
IT         3     24-12-2022T08:30  true
IT         2     14-11-2021T08:30  true
IT         1     22-11-2020T08:30  false
HR         33    24-12-2022T08:30  false
HR         22    14-11-2021T08:30  true
HR         11    22-11-2020T08:30  false

Ожидаемый результат:

Deprt      ID        StrtDT        flag
IT         3     24-12-2022T08:30  true
IT         2     14-11-2021T08:30  true
HR         22     14-11-2021T08:30  true
HR         33     24-12-2022T08:30  false
IT         1     22-11-2020T08:30  false 
HR         11     22-11-2020T08:30  false 

Пытался:

this.data.forEach(x=>{
        console.info('c??',x)
        x.Employees.sort((a:any,b:any)=>{ return a.StrtDT- b.StrtDT})})

Здесь я ищу, чтобы отсортировать сначала по флагу, а затем по дате от недавней до старой.

даже хотел бы рассмотреть любой другой подход для получения желаемого результата.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
80
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Отсортируйте массив по нескольким полям, сравните флаги, если они совпадают с датами разбора, и сравните их:

Обновление: вам нужно расширить массив сотрудников информацией об отделе. Затем сгладьте массив, чтобы получить массив сотрудников, а затем отсортируйте его.

let arr = [{  'Deprt': 'IT',
       'Employees': [ { 'ID': 3, 'StrtDT': '24-12-2022T08:30', 'flag': true },
           { 'ID': 2, 'StrtDT': '14-11-2021T08:30' , 'flag': true },
           { 'ID': 1, 'StrtDT': '22-11-2020T08:30', 'flag': false }]
   },
       {  'Deprt': 'HR',
           'Employees': [ { 'ID': 33, 'StrtDT': '24-12-2022T08:30', 'flag': false},
               { 'ID': 22, 'StrtDT': '14-11-2021T08:30',  'flag': true },
               { 'ID': 11, 'StrtDT': '22-11-2020T08:30', 'flag': false }]
       },
       {  'Deprt' : 'AC', 'Employees': []} ];

  arr.forEach(o => o.Employees.forEach(e => e.Deprt = o.Deprt));
  arr = arr.flatMap(o => o.Employees);
  
   arr.sort( (a,b) => {
       if (a.flag !== b.flag) {
           return a.flag ? -1 : 1;
       } else {
           let [d,mon,y,h,min] = a.StrtDT.split(/\D/);
           const d1 = new Date(y, mon-1, d, h, min);

           [d,mon,y,h,min] = b.StrtDT.split(/\D/);
           const d2 = new Date(y, mon-1, d, h, min);

           return d2-d1;
       }
   } );


  console.info(arr);

Это по-прежнему сортируется внутри отдела. Они хотят показать данные по отделам на основе этих двух полей. ЕСЛИ вы видите их ожидаемый результат, значит, есть 2 IT сверху и один посередине.

adiga 25.01.2023 11:23
Ответ принят как подходящий

Поскольку вы хотите отсортировать по отделам, вы не можете использовать исходные данные. Получите плоский массив сотрудников со свойством Deprt.

data.flatMap(({ Deprt, Employees }) => 
  Employees.map(emp => ({ ...emp, Deprt, StartDate: getDate(emp.StrtDT) }))
)

Кроме того, вам нужно добавить еще одно свойство под названием StartDate. Ваш текущий формат не может быть напрямую преобразован в дату. Итак, вам нужно использовать регулярное выражение, чтобы получить каждую часть даты и времени и преобразовать ее в дату

function getDate(dateStr) {
  const [d, m, y, h, min] = dateStr.match(/\d+/g)
  return new Date(y, m-1, d, h, min)
}

А потом sort сначала по flag, а потом по StartDate

array.sort((a, b) => b.flag - a.flag 
    || b.StartDate - a.StartDate
)

Вот фрагмент:

const data = [
  {
    Deprt: 'IT',
    Employees: [
      { ID: 3, StrtDT: '24-12-2022T08:30', flag: true },
      { ID: 2, StrtDT: '14-11-2021T08:30', flag: true },
      { ID: 1, StrtDT: '22-11-2020T08:30', flag: false },
    ],
  },
  {
    Deprt: 'HR',
    Employees: [
      { ID: 33, StrtDT: '24-12-2022T08:30', flag: false },
      { ID: 22, StrtDT: '14-11-2021T08:30', flag: true },
      { ID: 11, StrtDT: '22-11-2020T08:30', flag: false },
    ],
  },
];

function getDate(dateStr) {
  const [d, m, y, h, min] = dateStr.match(/\d+/g)
  return new Date(y, m-1, d, h, min)
}

const expected =
  data.flatMap(({ Deprt, Employees}) =>
    Employees.map(emp => ({ ...emp, Deprt, StartDate: getDate(emp.StrtDT) }))
  )
  .sort((a, b) => b.flag - a.flag 
  || b.StartDate - a.StartDate
  )

console.info(expected)
new Date(a.StrtDT) вернет неверную дату.
Jan Pfeifer 25.01.2023 11:40

Здравствуйте @adiga, спасибо за вашу помощь, ваш код работает как шарм, просто у меня проблема с датами. Знаете ли вы, почему моя дата меняется, например, с 2023-01-23T17:15 на 1928-07-15T16:15:00.000Z, не могли бы вы помочь мне с этим? Мне нужна та же дата и формат

R. Baraiya 25.01.2023 12:15

@R.Baraiya, это другой формат даты. 2023-01-23T17:15 можно напрямую анализировать без регулярного выражения.

adiga 25.01.2023 12:26

У меня прямая new date(emp.StrtDT) сработала отлично, еще раз спасибо @adiga

R. Baraiya 25.01.2023 12:26

@ R.Baraiya, какой формат даты у вас есть в вашем реальном коде?

adiga 25.01.2023 12:26

у меня такой же формат

R. Baraiya 25.01.2023 12:27

@ Р.Барайя 2023-01-23T17:15 или 24-12-2022T08:30 ?

adiga 25.01.2023 12:27

Вы правы, с моим фактическим кодом у меня есть yyyymmdd, извините за путаницу.

R. Baraiya 25.01.2023 12:29

@ R.Baraiya Тогда у вас нет дополнительной собственности. Просто .sort((a, b) => b.flag - a.flag || new Date(b.StrtDT) - new Date(a.StrtDT))

adiga 25.01.2023 12:29

Хорошее решение @adiga, у меня есть вопрос, что, если нам нужно показать разные сокращения для обоих флагов «нет / выкл», например, для флага со старой на будущую дату и для флага с будущей на старую дату?

user20042770 25.01.2023 13:05

@user20042770 user20042770, тогда вам нужно выполнить вторую сортировку условно: .sort((a, b) => b.flag - a.flag || ( a.flag ? a.StartDate - b.StartDate : b.StartDate - a.StartDate) )

adiga 25.01.2023 13:41

Другие вопросы по теме