0

I am trying to sort the following object array in desc order.

const data = [
  {
    scheduledTime: '22:00',
    arrivalTime: '22:12',
  },
  {
    scheduledTime: '20:10',
    arrivalTime: undefined,
  },
  {
    scheduledTime: '08:55',
    arrivalTime: '23:12',
  },
  {
    scheduledTime: '08:55',
    arrivalTime: undefined,
  },
  {
    scheduledTime: '09:55',
    arrivalTime: undefined,
  },
];

The rules are, first sort by "arrivalTime" and then by "scheduledTime". All undefined values of "arrivalTime" must be at the end of the array. Once all the undefined values from "arrivalTime" are at the end of the array, then it must be sorted again by "scheduledTime" in desc.

Here is what I have currently:

const multiSort = data.sort(function(a, b) {
  if (a.arrivalTime === undefined) return 1;
  if (b.arrivalTime === undefined) return -1;
  if (a.arrivalTime === b.arrivalTime) return 0;

  if (a.arrivalTime > b.arrivalTime) return -1;
  if (a.arrivalTime < b.arrivalTime) return 1;

  return a.scheduledTime < b.scheduledTime ? 1 : -1;
});

What the output is:

  0: {scheduledTime: "08:55", arrivalTime: "23:12"}
  1: {scheduledTime: "22:00", arrivalTime: "22:12"}
  2: {scheduledTime: "20:10", arrivalTime: undefined} //scheduledTime not in desc
  3: {scheduledTime: "08:55", arrivalTime: undefined} //scheduledTime not in desc
  4: {scheduledTime: "09:55", arrivalTime: undefined} //scheduledTime not in desc

Desire output:

  0: {scheduledTime: "08:55", arrivalTime: "23:12"}
  1: {scheduledTime: "22:00", arrivalTime: "22:12"}
  2: {scheduledTime: "20:10", arrivalTime: undefined} //scheduledTime in desc
  3: {scheduledTime: "09:55", arrivalTime: undefined} //scheduledTime in desc
  4: {scheduledTime: "08:55", arrivalTime: undefined} //scheduledTime in desc

Thanks in advance :)

6 Answers 6

1

I think this will solve your problem:

  const multiSort = data.sort(function(a, b) {
    if (a.arrivalTime === undefined){
        if(b.arrivalTime === undefined) {
            return a.scheduledTime < b.scheduledTime ? 1 : -1;
        } else {
            return 1;
        }
    }
    if (b.arrivalTime === undefined) { // At this point a.arrivalTime cannot be undefined
        return -1;
    }
    if (a.arrivalTime === b.arrivalTime) {
        return a.scheduledTime < b.scheduledTime ? 1 : -1;
    }

    if (a.arrivalTime > b.arrivalTime) return -1;
    if (a.arrivalTime < b.arrivalTime) return 1;
  });

Try it out and let me know, you should have more test cases just to make sure.

Sign up to request clarification or add additional context in comments.

3 Comments

string compare is not safe. if wont give u desire solution, u have to convert in hr,min.
Yeah, you're right, we're comparing strings actually and they represent time, but can you give me an example of when the solution would not work? I'm trying to think of one and I can't come up with a counterexample
Awesome, this works, thanks. :) I am now trying to add in another variable 'number' to be sorted in asc if the "scheduledTime" are equal; I am having trouble adding it to your code.
1

Try checking both a.arrivalTime and b.arrivalTime is undefined

const data = [{
    scheduledTime: '22:00',
    arrivalTime: '22:12',
  },
  {
    scheduledTime: '20:10',
    arrivalTime: undefined,
  },
  {
    scheduledTime: '08:55',
    arrivalTime: '23:12',
  },
  {
    scheduledTime: '08:55',
    arrivalTime: undefined,
  },
  {
    scheduledTime: '09:55',
    arrivalTime: undefined,
  },
];

const multiSort = data.sort(function(a, b) {
  if (a.arrivalTime === undefined && b.arrivalTime === undefined) {
    return a.scheduledTime < b.scheduledTime ? 1 : -1;
  }
  if (a.arrivalTime === undefined) return 1;
  if (b.arrivalTime === undefined) return -1;
  return a.arrivalTime < b.arrivalTime ? 1 : -1;
});

console.log(multiSort)

2 Comments

I think that solution doesn't compare arrivalTimes
string compare is not safe. if wont give u desire solution, u have to convert in hr,min.
0

you can use lodash sortBy for this.

_.sortBy(array, ['key1', 'key2'])

link to lodash

1 Comment

I can't use lodash since it sorts undefined to the top. And I have tried change the data structure to suit lodash, but I was told not to do it that way.
0

Let's take a look what happens in your code if we compare the following two objects:

const firstTime = {
  scheduledTime: '20:10',
  arrivalTime: undefined,
}

const secondTime = {
  scheduledTime: '09:55',
  arrivalTime: undefined,
}

sort(firstTime, secondTime)

function sort (a, b) {
  if (a.arrivalTime === undefined) return 1; // this returns 1 already, since firstTime.arrivalTime === undefined. The rest of your code is never executed
  if (b.arrivalTime === undefined) return -1;
  if (a.arrivalTime === b.arrivalTime) return 0;

  if (a.arrivalTime > b.arrivalTime) return -1;
  if (a.arrivalTime < b.arrivalTime) return 1;

  return a.scheduledTime < b.scheduledTime ? 1 : -1;
}

To change that, you need to nest your loops. I created a working example on CodePen: https://codepen.io/mewitte-the-flexboxer/pen/dyogGQx

Comments

0

Using basic conversion, I end-up with this solution.

const data = [{ scheduledTime: '22:00', arrivalTime: '22:12', }, { scheduledTime: '20:10', arrivalTime: undefined, }, { scheduledTime: '08:55', arrivalTime: '23:12', }, { scheduledTime: '08:55', arrivalTime: undefined, }, { scheduledTime: '09:55', arrivalTime: undefined, }, ];
const date = str => {
  if (!str) return 0;
  const [h, m] = str.split(":");
  return Number(h) * 60 + Number(m);
};
const dateDiff = (t1, t2) => date(t2) - date(t1);
const sortByArvAndSchDate = (
  { arrivalTime: aa, scheduledTime: aas },
  { arrivalTime: ba, scheduledTime: bas }
) => {
  const diff = dateDiff(aa, ba);
  return diff !== 0 ? diff : dateDiff(aas, bas);
};
const result = data.sort(sortByArvAndSchDate);
console.log(result);

3 Comments

Thanks, this will work, but I'm not supposed to change the data structure.
Where is data change?? It sort.. There is no data change in original data
Above data is just stringify of json.. To make code look nicer.. It will be same as object
0

If arrivalTimes are equal check for the scheduleTime for sorting.

Use '0' when values are undefined to move them to the end.

const data = [{ scheduledTime: '22:00', arrivalTime: '22:12', },{scheduledTime: '21:00',arrivalTime: '22:12'}, { scheduledTime: '20:10', arrivalTime: undefined, }, { scheduledTime: '08:55', arrivalTime: '23:12', }, { scheduledTime: '08:55', arrivalTime: undefined, }, { scheduledTime: '09:55', arrivalTime: undefined, }, ];

data.sort((a, b) => {
  return (b.arrivalTime || '0').replace(':', '') - (a.arrivalTime || '0').replace(':', '') ||
    (b.scheduledTime || '0').replace(':', '') - (a.scheduledTime || '0').replace(':', '')
});

console.log(data)

4 Comments

This works in acs, but the desire result has to be desc.
just swap all a's and b's, Updated solution
I tried that already, that would push the undefined to the top of the array. T_T
@webber you needed to change the Infinity with 0 as well, check the updated solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.