How can nested json be sorted effectively based on two specific fields?

Example Data:

[{  'ID': objID(abc123), 
    'Department': 'IT',
    'Employees': [ { 'ID': 3, 'StartDate': '24-12-2022T08:30', 'active': true },          
                   { 'ID': 2, 'StartDate': '14-11-2021T08:30', 'active': true },
                   { 'ID': 1, 'StartDate': '22-11-2020T08:30', 'active': false }]
  },
  { 'ID': objID(def456),
    'Department': 'HR',
    'Employees': [ { 'ID': 33, 'StartDate': '24-12-2022T08:30', 'active': false},          
                   { 'ID': 22, 'StartDate': '14-11-2021T08:30', 'active': true },
                   { 'ID': 11, 'StartDate': '22-11-2020T08:30', 'active': false }]
  },
  {  'ID': objID(ghi789),'Department' : 'AC', 'Employees': []}... more than 1000 ]

Table HTML Code:

<tbody>
   <ng-container *ngFor="let dept of Department">
     <tr *ngFor="let emp of dept.Employees" class="card-text">
       <td> {{dept.Department}} </td>
       <td> {{emp.ID}}   </td>
       <td> {{emp.StartDate}}  </td>
       <td> {{emp.active}}  </td>
    </tr>
   </ng-container>
</tbody>

Current Display:

Department      ID        StartDate        active
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:

Department      ID        StartDate        active
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 

Attempted Solution:

this.data.forEach(entry => {
        console.log('checking:', entry)
        entry.Employees.sort((a:any, b:any) => { return a.StartDate - b.StartDate })})

In this case, I am aiming to sort the data first by activity status and then by dates from recent to oldest.

I am open to exploring alternative methods to achieve the desired output.

Answer №1

To efficiently sort employees across departments, it is necessary to transform the data structure. Create a flat array of employees with a "Deprt" property.

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

In addition, include a new property called "StartDate". The current format of dates needs to be converted using regex to obtain date and time components for proper conversion to Date objects.

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

Subsequently, implement sorting based on "flag" and then "StartDate".

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

An illustrative example:

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 convertToDate(dateStr) {
  const [d, m, y, h, min] = dateStr.match(/\d+/g)
  return new Date(y, m-1, d, h, min)
}

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

console.log(sortedEmployees)

Answer №2

Organize an array by various criteria, compare flags, and if they match, analyze dates for a comparison:

Note: To enhance the employee array, incorporate department information. Then streamline the array to obtain a list of employees and proceed with sorting.

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to construct a JSON object for React based on the data from a JSON API response?

My API will be sending back data in the following format: [ { "id":5, "name":"Example", }, { "id":634, "name":"Test", }, ... ] In my React application, I need to create a JSON object like this: const fields = ...

Enhancing UI design with Vue.js

I'm attempting to customize elements using data from a JSON file in Vue.js: <div v-for="(item, index) in json._items" class="help-inner-callout" v-html="item.text" style="top:item.top; left: item.left;">&l ...

Sleek transitions for navigating between cells in a data table

I am looking to implement a smooth animation for cell navigation. Check out what I currently have: http://jsfiddle.net/0ardb3u0/ When the mouse hovers over a cell, I want the full column and row of that cell to be selected and highlighted in blue. How ...

Is your website's Google analytics event tracking not giving you the feedback you need

Here's what I'm trying to achieve in the code below: Set up Google Analytics on the page Add a jQuery click event based on specific query strings and domain characters Trigger a Google Analytics tracking event with the click event Implement cod ...

Attempting to fetch JSON information but encountering an error message stating "not a valid function."

I have been working on developing a programmer job board app and I am currently facing an issue with displaying JSON data on the main page. My goal is to eventually render the data, but for now, I just want to ensure that it appears in JSON format so that ...

Exploring Opencascade.js: Uncovering the Real Text within a TCollection_ExtendedString

I am currently attempting to retrieve the name of an assembly part that I have extracted from a .step file. My method is inspired by a blog post found at , however, I am implementing it using javascript. I have managed to extract the TDataStd_Name attribut ...

Dealing with errors in node.js

Node.js asynchronous functions typically have a callback, with some like fs.writeFile passing an err argument. fs.writeFile('message.txt', 'Hello Node', function (err) { if (err) throw err; console.log('It\'s saved!& ...

Optimal strategies for managing subscriptions in Angular

I'm currently pondering about the concept of angular subscription and unsubscription. The amount of information available on this topic is overwhelming, making it hard for me to navigate through. When is the right time to unsubscribe from a subscript ...

NodeJS does not support the Array.Push method

I'm having trouble getting this code to work. I want to generate 5 random items from my database and store them in an array called 'dato'. However, when I print the array, it appears to be empty. /* GET users listing. */ router.get('/& ...

"NaN is being caused by the presence of quotation marks within the split property

Apologies if this question has already been addressed, but I'm struggling to find the answer. I've recently delved into coding as a new hobby and found it quite enjoyable. After using a website that claimed I had learned all there is to know abou ...

Tips for executing an asynchronous fetch prior to the first rendering

Currently, I am working with the Wordpress API using Next.js on the front end. My goal is to fetch my navigation/menu data and have it pre-rendered. However, my attempts have only resulted in an empty <nav> </nav> element being rendered when I ...

Is there a way to display the HTML input date by simply clicking on text or an image?

I need to display a date picker when I click on specific text or an image. I am working with reactjs and utilizing the HTML input type="date", rather than the React-datepicker library. Here is the code snippet: import { useRef } from "r ...

What is the best way to handle reading hefty files using the fs.read method and a buffer in JavaScript?

I'm currently delving into the world of javascript, and one of my go-to exercises when learning a new programming language is to create a hex-dump program. The main requirements for this program are: 1. to read a file provided through the command line ...

Using object syntax in React state management

I've been working on dynamically updating the state in my React app, and this is what the current state looks like: this.state = { title: "", image: "", imageFile: "", formTitle: "", formMessage: "", formImage: "", ...

Utilize Moment to retrieve the weekend dates

Currently tackling a date-related issue and feeling stuck. Is it feasible to extract weekends from an array of dates using Moment.js instead of the getDay() method? I'm a beginner in JavaScript. ...

Depend on a mapping function to assign a value to every option within a discriminated union

While utilizing all variations of a discriminated union with conditional if statements in TypeScript, the type is narrowed down to the specific variant. To achieve the same effect by expressing the logic through a mapping from the discriminant to a funct ...

Changing the input to uppercase within Vue.js

I am looking to capitalize the input data from the user's full name model and would prefer if it is in Latin letters only. Utilizing Vue.js for Uppercase Conversion <p-input :value="value" @input="$emit('input', $event)&qu ...

Exploring the power of jQuery closures and handling events like mouseover and mouseout

I'm currently grappling with the concept of utilizing closures in conjunction with jQuery event functions. The challenge I am facing involves creating rounded shapes on the screen that stop and fade when hovered over, then resume fading when the mous ...

What could be causing the Multer error in my Express.js application when attempting to upload a file for the second time, even though the first time was successful?

Whenever I try to upload a single file, the code works flawlessly. However, if I attempt to upload another file, I encounter the following Multer error: Error code: 'LIMIT_UNEXPECTED_FILE', field: 'myFile', storageErrors: [] To succes ...

A tiny blue spot popping up beside the roster of users

I'm working on a render function that displays a list of users with avatars and names. The issue I'm facing is that when the page initially loads, there's a blue dot to the left of each user. However, if I navigate to another page and then g ...