Wcan Wcan - 1 month ago 9
Javascript Question

Javascript sort with condition gives out of order result

Before I start I've looked at a lot of posts but i don't know how to solve this issue. I have a an array which I'm sorting with a condition as following, I want any array item which matches the tablePrefix on top. When the number of items in array is 10 OR less than 10 its works like a charm but when it is 11 OR more the function starts giving wrong sorting order.

var tablePrefix = 'es_officer';

columns = [
"es_officer_id", // 0
"es_officer_name", // 1
"es_officer_fname", // 2
"es_officer_dob", // 3
"es_officer_apply_status", // 4
"es_employment_type_id", // 5
"es_employment_type_name", // 6
"es_designation_id", // 7
"es_designation_title", // 8
"es_service_type_id", // 9
"es_service_type_name", // 10
"es_bps_id", // 11
"es_bps_title" // 12
];

columns.sort((a, b) => a.indexOf(tablePrefix) ? a.localeCompare(b) : -1);

console.log(columns);


Result with 12 items in array

[
"es_officer_id",
"es_officer_fname",
"es_officer_dob",
"es_officer_apply_status",
"es_bps_id",
"es_officer_name", // Unordered result, this should be above es_bps_id
"es_bps_title",
"es_designation_id",
"es_designation_title",
"es_employment_type_id",
"es_employment_type_name",
"es_service_type_id",
"es_service_type_name"
]


but if remove any two items and reduce the no of items in columns array to 10 it works fine. for example lets remove 9 and 10.

Result with 10 items in array

[
"es_officer_id",
"es_officer_fname",
"es_officer_dob",
"es_officer_apply_status",
"es_officer_name", // In right order
"es_bps_id",
"es_bps_title",
"es_designation_id",
"es_designation_title",
"es_employment_type_id",
"es_employment_type_name"
]


Anyone ?? help will be appreciated.

Answer

Sorting algorithms assume a total consistent ordering. This means that it must not be possible that both a < b and b < a, but this is what happens when you compare two elements matching the prefix as cmp will return -1 even if you swap the elements.

If you violate algorithm requirements about comparison function then anything can happen (for example a bubble sort algorithm would loop forever). Apparently the ECMA standard is more forgiving and just talks about arbitrary implementation-defined sort order: hang, crash or element duplication/deletion is not going to happen in a compliant implementation.

Note also that if a matches you need to check if b matches too before using localCompare if you want all matching to appear before.

function comp(a, b) {
   if (a.indexOf(prefix)) {
      if (b.indexOf(prefix)) {
          return a.localCompare(b);
      } else {
          return 1;
      }
   } else {
      if (b.indexOf(prefix)) {
          return -1;
      } else {
          return 0; // All prefixed are considered equal
      }
   }
}
Comments