Home > Mobile >  What is the most efficient way to sort nested json by two fields?
What is the most efficient way to sort nested json by two fields?

Time:01-26

Data Sample:

[{  '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 code to show in table:

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

Current Output:

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

Expected Output:

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 

Tried:

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

Here I am looking for to sort first by flag and then by dates recent to old.

even, would like to consider any different approach to get desire output.

CodePudding user response:

Since you want to sort across departments, you can't use the original data. Get a flat array of employees with a Deprt property.

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

Also, you need to add another property called StartDate. Your current format cannot be converted to a Date directly. So, you need to use regex to get each date time parts and convert it to Date

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

And then sort firstly based on the flag and then by StartDate

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

Here's a snippet:

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.log(expected)

CodePudding user response:

Sort array by multiple fields, compare flags, if they are the same parse dates and compare them:

Update: you need to extend emloyees array with department info. Then flatten array to get array of employees and then sort it.

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.log(arr);

  • Related