Home > database >  Sorting and ordering an array with different criteria
Sorting and ordering an array with different criteria

Time:04-09

I am trying to implement sorting and order to an array.

The challenge which I am facing is that I have 5 criteria on which to base my sorting, which are:

  1. due_date === 1000
  2. status && is_approved(boolean)
  3. is_overdue(boolean checking with date-fns using the due_date)
  4. due_date (either null, or number)
  5. is_approved

What I would like to achieve is to create a sorting function which orders the above criteria as the following (from highest to lowest):

  1. due_date === 1000

  2. is_overdue (I am using isAfter of the date-fns which returns a boolean)

  3. status === 'DONE' && !is_approved

  4. due_date starting from lowest to highest (ignore the null values)

  5. is_approved === true

  6. any other remaining object

I was thinking of perhaps running .map method, and appending a ranking value for each of the object by checking the criteria, but there must be a way of doing this in single iteration with .sort method. I already checked other StackOverflow threads, but most of their data is relatively simple such as age, name etc.

[
    {
      due_date: 150000,
      is_approved: false,
      is_overdue: true,
      status: 'TODO',
    },
    {
      due_date: 200000,
      is_approved: true,
      is_overdue: false,
      status: 'DONE',
    },
    {
      due_date: 150000,
      is_approved: false,
      is_overdue: false,
      status: 'IN PROGRESS',
    },
    {
      due_date: 1000,
      is_approved: false,
      is_overdue: true,
      status: 'TODO',
    },
    {
      due_date: 200000,
      is_approved: true,
      is_overdue: false,
      status: 'DONE',
    },
    {
      due_date: null,
      is_approved: false,
      is_overdue: true,
      status: 'TODO',
    },
  ]

Which I want to transform to;

[
    {
      due_date: 1000, // By due_date 1000 - highest ranking
      is_approved: false,
      is_overdue: true,
      status: 'TODO',
    },
    {
      due_date: 150000,
      is_approved: false,
      is_overdue: true, // Is overdue - second highest
      status: 'TODO',
    },
    {
      due_date: null,
      is_approved: false,
      is_overdue: true, // Is overdue - second highest
      status: 'TODO',
    },
    {
      due_date: 200000,
      is_approved: false, // Is not yet approved
      is_overdue: false,
      status: 'DONE', // and Is DONE
    },
    {
      due_date: 150000,
      is_approved: false,
      is_overdue: false,
      status: 'IN PROGRESS',
    },
    {
      due_date: 200000, // Lowest ranked
      is_approved: true, // Is APPROVED approved
      is_overdue: false,
      status: 'DONE', // and is DONE
    },
  ]

CodePudding user response:

You just need to define a sorting function

I've implemented the first two requirements I leave the rest to you

Probably it needs a bit of refactoring but you get the idea

const data = [
    {
      due_date: 150000,
      is_approved: false,
      is_overdue: true,
      status: 'TODO',
    },
    {
      due_date: 200000,
      is_approved: true,
      is_overdue: false,
      status: 'DONE',
    },
    {
      due_date: 150000,
      is_approved: false,
      is_overdue: false,
      status: 'IN PROGRESS',
    },
    {
      due_date: 1000,
      is_approved: false,
      is_overdue: true,
      status: 'TODO',
    },
    {
      due_date: 200000,
      is_approved: true,
      is_overdue: false,
      status: 'DONE',
    },
    {
      due_date: null,
      is_approved: false,
      is_overdue: true,
      status: 'TODO',
    },
  ]
  
  
 const sortingFn = (a, b) => {
  if(a.due_date === 1000){
    return -1
  }
  if(b.due_date === 1000){
    return 1
  }
  
  if(a.is_overdue){
    return -1
  }
 
   if(b.is_overdue){
    return 1
  }
  //the rest of the conditions
 }
 
 data.sort(sortingFn)
 console.log(data)

CodePudding user response:

The deltas of boolean value are reversed. Theat mean if you like to sort true to top, you need to use b - a.

You could have a look to the wanted propeties and their values:

  • due_date === 1000 (desc)
  • is_overdue (desc)
  • is_approved (asc)
  • status === 'DONE' !is_approved (sum asc)
  • due_date === null (asc)
  • due_date (desc)

const
    data = [{ due_date: 150000, is_approved: false, is_overdue: true, status: 'TODO' }, { due_date: 200000, is_approved: true, is_overdue: false, status: 'DONE' }, { due_date: 150000, is_approved: false, is_overdue: false, status: 'IN PROGRESS' }, { due_date: 1000, is_approved: false, is_overdue: true, status: 'TODO' }, { due_date: 200000, is_approved: false, is_overdue: false, status: 'DONE' }, { due_date: null, is_approved: false, is_overdue: true, status: 'TODO' }];

data.sort((a, b) =>
    (b.due_date === 1000) - (a.due_date === 1000) ||
    b.is_overdue - a.is_overdue ||
    a.is_approved - b.is_approved ||
    (a.status === 'DONE'   !a.is_approved) - (b.status === 'DONE'   !b.is_approved) ||
    (a.due_date === null) - (b.due_date === null) ||
    b.due_date - a.due_date 
);

console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

  • Related