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

angular.js:13920 Alert: [ngRepeat:dupes] Multiple occurrences in a repeater

I encountered an issue while attempting to parse a JSON file and map it in HTML. Here is the JavaScript code snippet: searhController.orderlogs.results = JSON.stringify(response.data); This is how it's implemented in Angular: <tr ng-hide="searh ...

Having trouble resolving "react-native-screens" from "node_modules eact-navigation-stacklibmoduleviewsStackViewStackViewCard.js"? Here's how to fix it

Here is the command I used for setting up react app routes: npm i react-native-router-flux --save After restarting npm with "npm start," I encountered this error message: Unable to resolve "react-native-screens" from "node_modules\react-navigation- ...

Creating a callback function within stored procedures using JavaScript Language Integrated Query in documentDB: A step-by-step guide

According to the documentation, the code snippets below are considered equivalent. However, I have observed that in the first case, I am able to perform operations on multiple documents within the callback function, whereas the map function in the latter s ...

Enhance video playback by eliminating accidental scrolling through the space bar

When using a video player, I always prefer to pause it by pressing the spacebar. However, this function is not working as expected. The issue at hand is that instead of pausing the video, pressing the space bar causes the page to scroll down unexpectedly ...

Performing calculations on two properties of an observable object in Angular 8 and then storing the result in a new property

Looking for guidance on how to display the sum of two properties from an observable data. Take a look at the code below and let me know your thoughts: Typescript class export class Amount { Amount1: number; Amount2: number; Total:number; } In typescript ...

Leverage the hidden glitch lurking within Vue

While working with SCSS in vue-cli3, I encountered a strange bug where using /deep/ would result in errors that I prefer not to deal with. Code Running Environment: vue-cli3 + vant + scss CSS: /deep/ .van-tabs__content.van-tabs__content--animated, .va ...

Pay attention to the input field once the hidden attribute is toggled off

In attempting to shift my attention to the input element following a click on the edit button, I designed the code below. The purpose of the edit is to change the hidden attribute to false. Here's what I attempted: editMyLink(i, currentState) { ...

Engaging grid connected to MySQLi database table

I am new to programming and have been diving into the world of PHP and MySQLi. I understand that the task at hand requires more expertise than what I currently possess. My project involves creating a 3x3 grid where only one square per row can be selected. ...

Oops! Looks like we encountered a problem: "Uncaught ReferenceError: process is not

As I work on my project utilizing angular 6 with Spring-boot, I have encountered an error that I am struggling to resolve. Specifically, the error message reads: Uncaught ReferenceError: process is not defined at Object../node_modules/util/util.js (ut ...

Showing button based on a particular value

I am trying to dynamically display a button based on the value of the sendSMS property for the logged-in user. I have added this property in the viewer model, which is connected to the user's base model. However, I am encountering difficulties with us ...

Retrieving JSON information stored in a JavaScript variable

I'm feeling a bit embarrassed to admit it, but I am still learning the ropes when it comes to Javascript development. I've hit a roadblock and could really use some help from the experts here. Thank you in advance for all the assistance this comm ...

injecting javascript dynamically using jquery

I am attempting to conditionally load a script in the case that the browser being used is IE8. To achieve this, I have employed jQuery's .getScript function as it allows me to execute certain actions after the script has been loaded. The issue lies in ...

Tips for retrieving a string instead of an Observable in @angular/http

I'm currently integrating Angular 4 with .NET Core Web API. The Web API is providing a CustomerName as a string based on the Id given. Here is the service method in Angular 4. I know that angular/http needs to return an Observable due to it being an ...

What is the difference between using 'classes' and 'className' in Material UI?

I find myself a bit perplexed about these two properties. Let's say I have, const useStyles = makeStyles(() => ({ style: { width: 600, height: 400, }, })); With this, I can use, const classes = useStyles(); <SomeComponent classNa ...

When working with Node.js, it is important to properly export your Oracle database connection to avoid encountering an error like "TypeError: Cannot read property 'execute

Hey there, I am a newbie when it comes to Node.js and Oracle. I've managed to create an app and establish a successful connection to the database. Now, I'm trying to figure out how to utilize the connection object throughout my application. Any s ...

I have implemented the ag grid date filter, but I am having trouble getting the apply and reset buttons to work properly within the filter

Currently, I am facing an issue with the ag grid date filter implementation. I am attempting to add both apply and reset buttons to the filter, but the code I have used does not seem to be functioning correctly. Here is the column definition code snippet ...

What could be the reason for the HTML canvas not displaying anything after a new element is added?

How come the HTML canvas stops showing anything after adding a new element? Here is my HTML canvas, which works perfectly fine until I add a new element to the DOM: <canvas class="id-canvas", width="1025", height="600"> ...

Renew the php blade foreach loop using jQuery to update data live

I have a foreach cycle in my HTML, and at one point, some data is posted from JavaScript. I would like to append it once it is added to the database. I need to find a way to refresh the foreach loop without reloading the entire page (I could simply use ap ...

Rerendering of a React component occurs upon a change in its state

Previously, my form was functioning flawlessly. However, after making a few modifications to the state variables, the input field now loses focus upon a state change. I am utilizing MUI and everything was working perfectly until this sudden issue arose f ...

io-ts: Defining mandatory and optional keys within an object using a literal union

I am currently in the process of defining a new codec using io-ts. Once completed, I want the structure to resemble the following: type General = unknown; type SupportedEnv = 'required' | 'optional' type Supported = { required: Gene ...