How to correctly sort these type of array?

82 Views Asked by At

I am in trouble with this sort. I have an array containing values like this:

array = [ {SortTime : 123456, Operation : Assigning}, {SortTime : 4567 , Operation: Assigning}, {SortTime : 123456 , Operation: Assigned} ]; 

So if I compare array[0] and array[2] I would like to keep the order so that I have "Assigning" before of "Assigned"

Everyone of these number is an epoch number so I need that if the algorithm works with two equals numbers it leave the same initial order for these two numbers (if I have array[4] = 12345 and array[5] = 12345, I want that array[4] and array[5] don't become array[5] and array[4] in the order).

    array.sort(function(a, b) {
        if (a.val.SortTime === b.val.SortTime) {
            return -1;
        } else {
            return a.val.SortTime - b.val.SortTime;
        }
    });

This doens't work because often make swap of position between equals number. I am sorry if my explanation is bad. Thank you in advance!

3

There are 3 best solutions below

0
Nina Scholz On BEST ANSWER

You could add to the objects an index property and sort by time and then by index, to keep the relation of same time items.

The result is a stable result, because of the taken index.

var array = [
        { SortTime: 123456, Operation: 'Assigning', index: 0 },
        { SortTime: 4567, Operation: 'Assigning', index: 1 },
        { SortTime: 123456, Operation: 'Assigned', index: 2 }
    ]; 

array.sort(function (a, b) {
    return a.SortTime - b.SortTime || a.index - b.index;
});

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

0
glennsl On

What you want is a stable sort. See Wikipedia for a list of stable sort algorithms

Here's a merge sort implementation from Rosetta Code:

function merge(left, right, arr) {
  var a = 0;
 
  while (left.length && right.length) {
    arr[a++] = (right[0] < left[0]) ? right.shift() : left.shift();
  }
  while (left.length) {
    arr[a++] = left.shift();
  }
  while (right.length) {
    arr[a++] = right.shift();
  }
}
 
function mergeSort(arr) {
  var len = arr.length;
 
  if (len === 1) { return; }
 
  var mid = Math.floor(len / 2),
      left = arr.slice(0, mid),
      right = arr.slice(mid);
 
  mergeSort(left);
  mergeSort(right);
  merge(left, right, arr);
}
 
var arr = [1, 5, 2, 7, 3, 9, 4, 6, 8];
console.log(arr);
mergeSort(arr)
console.log(arr);

0
Firanolfind On

There is working example at JSBin

var arr = [ 
     { 
       SortTime: 123456, 
       Operation: 'first operator'
     }, {
       SortTime: 4567,
       Operation: Assigning
     }, {
       SortTime: 123456,
       Operation: 'second operator'
     }];

var copy = [...arr];

copy.sort(function(a, b) {
    if (a.val.SortTime === b.val.SortTime) {
        return arr.indexOf(a) - arr.indexOf(b);
    } else {
        return a.val.SortTime - b.val.SortTime;
    }
});