1

I am trying to sort an array without it being alphabetical. In my case I want the order of the messages returned to be error, warning and then info. Reading about this at W3 I found a similar example...

They give this example with cars but have changed it too messages for my use case.

var message = [
  {type:"Error", message:"This is an Error"},
  {type:"Info", message:"This is an Info"},
  {type:"Warning" message:"This is a Warning"}
];


function myFunction() {
  message.sort(function(a, b){
    var x = a.type.toLowerCase();
    var y = b.type.toLowerCase();
    if (x < y) {return -1;}
    if (x > y) {return 1;}
    return 0;
  });
}

I thought this was all about scoring the value so I thought this might be right way to do it but it isnt giving me the expected results...

function myFunction() {
  message.sort(function(a, b){
    var x = a.type.toLowerCase();
    var y = b.type.toLowerCase();
    if (x === 'error') {return 1;}
    if (x === 'warning') {return 2;}
    if (x === 'info') {return 3;}
    return 0;
  });
}
Travis
  • 2,185
  • 7
  • 27
  • 42
  • 1, 2, and 3 will all produce the same sorting result. The [comparator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) should return a negative number, zero, or a positive number to indicate order. – ray Aug 05 '20 at 16:59
  • 1
    Does this answer your question? [Sort an array of object by a property (with custom order, not alphabetically)](https://stackoverflow.com/questions/47158756/sort-an-array-of-object-by-a-property-with-custom-order-not-alphabetically) – Josef Bláha Aug 05 '20 at 17:00

3 Answers3

1

You can compare y after each time you compare x:

var message = [
  {type:"Error", message:"This is an Error"},
  {type:"Info", message:"This is an Info"},
  {type:"Warning", message:"This is a Warning"}
];


function myFunction() {
  message.sort(function(a, b){
     var x = a.type.toLowerCase();
     var y = b.type.toLowerCase();
     if (x === 'error') {return -1;}
     else if(y === 'error'){return 1;}
     else if (x === 'warning') {return -1;}
     else if (y === 'warning') {return 1;}
     else if (x === 'info') {return -1;}
     else if (y === 'info') {return 1;}
     return 0;
  });
}

myFunction();
console.log(message);
Majed Badawi
  • 27,616
  • 4
  • 25
  • 48
  • 1
    Thank you very much, I wasn't sure the purpose of x vs y but seeing how you wrote that totally makes sense now. Thank you very much! – Travis Aug 05 '20 at 17:20
0

You could take an object with the wanted order and return the delta of the wanted order in the sorting callback.

For sorting unknown types to the end of the array use a large value.

const 
    order = { error: 1, warning: 2, info: 3, default: Number.MAX_VALUE },
    message = [{ type: '' }, { type: "Error", message: "This is an Error" }, { type: "Info", message: "This is an Info" }, { type: "Warning", message: "This is a Warning" }, { type: '' }];

message.sort(({ type: a }, { type: b }) =>
    (order[a.toLowerCase()] || order.default) - (order[b.toLowerCase()] || order.default)
);

console.log(message);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

You should have weights for all your log messages for filtering (and sorting, if that's what you need).

I adopted Java's java.util.logging.Level class to introduced various weights for log messages; depending on their severity.

/**
 * Based on:
 * https://docs.oracle.com/javase/8/docs/api/java/util/logging/Level.html
 */
const LogLevel = {
  OFF     : { value: Number.MAX_VALUE }, 
  ERROR   : { value: 1000             }, // Based on Level.SEVERE
  WARNING : { value: 900              },
  INFO    : { value: 800              },
  DEBUG   : { value: 500              }, // Based on Level.FINE
  ALL     : { value: Number.MIN_VALUE }
};

class LogUtils {
  static sortMesages(messages) {
    return messages.sort(({ type: a }, { type: b }) => {
      if (b == null || LogLevel[b.toUpperCase()] == null) return -1;
      if (a == null || LogLevel[a.toUpperCase()] == null) return 1;
      return LogLevel[b.toUpperCase()].value -
             LogLevel[a.toUpperCase()].value;
    });
  }
}

const logMessages = [
  { type: "Error",   message: "This is an Error"  },
  { type: "Info",    message: "This is an Info"   },
  { type: "Warning", message: "This is a Warning" }
];

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

Here are some other implementations of logging weights in third-party JS libraries:

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132