skip to Main Content

I was working on a solution to a leetcode problem (https://leetcode.com/problems/sender-with-largest-word-count/) when I hit a scenario I spent hours trying to debug and still can’t figure out what’s going on. To simplify, given an object:

let items = [
  [ 'K', 4 ],           [ 'kFIbpoFxn', 10 ],  [ 'yErgn', 6 ],
  [ 'N', 8 ],           [ 'wtJesr', 9 ],      [ 'rusffeL', 14 ],
  [ 'KlpoodEd', 5 ],    [ 'qGcQqIVdFr', 1 ],  [ 'ztmCdK', 10 ],
  [ 'HFILjKln', 12 ],   [ 'TmmQZ', 18 ],      [ 'R', 7 ],
  [ 'CNh', 7 ],         [ 'YMQDBkOWy', 22 ],  [ 'kjiSc', 4 ],
  [ 'cGMsZxxx', 6 ],    [ 'PPqsmNBewN', 21 ], [ 'gbtn', 10 ],
  [ 'nQNcL', 8 ],       [ 'rK', 10 ],         [ 'ppr', 16 ],
  [ 'LhSVp', 11 ],      [ 'Ub', 7 ],          [ 'QGRFMLY', 11 ],
  [ 'SdDObYkD', 9 ],    [ 'q', 3 ],           [ 'suAakSCuHz', 6 ],
  [ 'dnzhjdwrEt', 8 ],  [ 'ubIEXAO', 22 ],    [ 'EsBuLal', 11 ],
  [ 'xlQqQRrdTv', 12 ], [ 'mWxCG', 8 ],       [ 'DmwIEmS', 5 ],
  [ 'nBQLLS', 6 ],      [ 'QhF', 4 ],         [ 'bmtYQKYv', 5 ],
  [ 'PRiNk', 7 ],       [ 'QyYJw', 7 ],       [ 'QIFauTN', 3 ],
  [ 'zJLcUq', 13 ],     [ 'TU', 1 ],          [ 'lCkGjDY', 7 ],
  [ 'A', 6 ]
]

I am attempting to sort it based first on highest integer, but if those values are equal, by largest lexicographical value, ie the .reverse() of how JS sorts strings by default

my sorting code is:

items.sort(function(a, b) {
  return b[1] !== a[1] ? b[1] - a[1] : -a[0].localeCompare(b[0]);
});

resulting in:

[
  [ 'YMQDBkOWy', 22 ], [ 'ubIEXAO', 22 ],    [ 'PPqsmNBewN', 21 ],
  [ 'TmmQZ', 18 ],     [ 'ppr', 16 ],        [ 'rusffeL', 14 ],
  [ 'zJLcUq', 13 ],    [ 'xlQqQRrdTv', 12 ], [ 'HFILjKln', 12 ],
  [ 'QGRFMLY', 11 ],   [ 'LhSVp', 11 ],      [ 'EsBuLal', 11 ],
  [ 'ztmCdK', 10 ],    [ 'rK', 10 ],         [ 'kFIbpoFxn', 10 ],
  [ 'gbtn', 10 ],      [ 'wtJesr', 9 ],      [ 'SdDObYkD', 9 ],
  [ 'nQNcL', 8 ],      [ 'N', 8 ],           [ 'mWxCG', 8 ],
  [ 'dnzhjdwrEt', 8 ], [ 'Ub', 7 ],          [ 'R', 7 ],
  [ 'QyYJw', 7 ],      [ 'PRiNk', 7 ],       [ 'lCkGjDY', 7 ],
  [ 'CNh', 7 ],        [ 'yErgn', 6 ],       [ 'suAakSCuHz', 6 ],
  [ 'nBQLLS', 6 ],     [ 'cGMsZxxx', 6 ],    [ 'A', 6 ],
  [ 'KlpoodEd', 5 ],   [ 'DmwIEmS', 5 ],     [ 'bmtYQKYv', 5 ],
  [ 'QhF', 4 ],        [ 'kjiSc', 4 ],       [ 'K', 4 ],
  [ 'QIFauTN', 3 ],    [ 'q', 3 ],           [ 'TU', 1 ],
  [ 'qGcQqIVdFr', 1 ]
]

the issue is ‘ubIEXAO’ should be sorted ahead of ‘YMQDBkOWy’. when you do the isolated -a.compareLocale(b) it works correctly, and in other test cases this part of the code correctly sorts other strings. but not in this test case. what am I missing? thank you!

(I know there are myriad other ways to solve this problem, I just want to know why this sort function isn’t working as intended for this object)

2

Answers


  1. You can directly use the comparison operators to make it case sensitive.

    items.sort((a, b) => b[1] - a[1] || (b[0] > a[0]) - (b[0] < a[0]));
    
    Login or Signup to reply.
  2. It is because of the order of compareFn(a, b) value.

    a is the next item and b is the current item.

    So in this case the return result is equal to 1, which is > 0 so it will

    sort a after b, e.g. [b, a]. Sort order

    which is mean b will be placed before a ~ [ 'YMQDBkOWy', 22 ] before [ 'ubIEXAO', 22 ]

    a = [ 'ubIEXAO', 22 ]
    b = [ 'YMQDBkOWy', 22 ]
    
    -a[0].localeCompare(b[0]) =  1
    
    let items = [
      ["YMQDBkOWy", 22],
      ["ubIEXAO", 22],
    ];
    
    items.sort(function (a, b) {
      console.log("a is second item", a);
      console.log("b is first item", b);
    
      console.log("-a[0].localeCompare(b[0]) = ", -a[0].localeCompare(b[0])); // 1
    
      return -a[0].localeCompare(b[0]); // 1  > 0
    });
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search