0

I have an array that looks like this

['NAME', 5, '2. Defender', 'FALSE', 'TRUE', 'FALSE', 'undefined']
['NAME', 5, '4. Forward', 'TRUE', 'TRUE', 'FALSE', 'undefined']
['NAME', 5, '2. Defender', 'FALSE', 'TRUE', 'FALSE', 'undefined']
['NAME', 4, '4. Forward', 'FALSE', 'TRUE', 'FALSE', 'undefined']
['NAME', 3, '5. Midfielder', 'FALSE', 'FALSE', 'FALSE', 'undefined']

I am referencing this page on how to sort it, and this is what I have:

array.sort(
    function(a, b) {          
      if (a[1] === b[1]) {
        // Price is only important when cities are the same
        return b[2] - a[2];
      }
      return a[1] < b[1] ? 1 : -1;
  });

It only sorts by the [1] value and will not sort by the secondary [2] value. I thought there might be something wrong with my array, but when I switch things to sort by [2] first, then it sorts by that value fine. Though the goal is to sort by [1] first, and then secondarily sort by [2].

jons
  • 312
  • 2
  • 10
  • Why the jQuery tag? – MrUpsidown May 30 '22 at 20:33
  • Because I am writing it in jquery and must have been mistaken if this is pure javascript. (edited the post) – jons May 30 '22 at 20:34
  • *Why the downvote?* - you *could* have included a working code snippet that shows the issue. You *must* also provide debugging details. And your "array" is not an array. Thanks to provide a [mcve]. – MrUpsidown May 30 '22 at 20:37
  • I appreciate your time and like I said I did my best. Thankfully, @oyophant below provided the answer – jons May 30 '22 at 20:41

2 Answers2

0

The third array element [2] is a string which you can't compare by subtraction. Use .localeCompare instead

array.sort((a, b) => a[1] !== b[1] ? a[1] - b[1] : a[2].localeCompare(b[2]))
oyophant
  • 1,294
  • 12
  • 23
  • That works perfectly. Thank you so much for your time. Would there be a way to add a third value to sort by if I were to use [3]? – jons May 30 '22 at 20:42
  • 1
    You're welcome - of course you can always append more comparisons like `a[1] !== b[1] ? a[1]-b[1] : (a[2].localeCompare(b[2])!==0 ? a[2].localeCompare(b[2]) : a[3].localeCompare(b[3]))` – oyophant May 30 '22 at 20:44
  • Could I bother you to see an example adding in the [3] value? I have not been able to find that and would greatly appreciate it. – jons May 30 '22 at 20:45
  • Thank you so much again. Stack Overflow can be a daunting place and I appreciate your knowledge, kindness, and time. – jons May 30 '22 at 20:49
  • 1
    just edited the answer above – oyophant May 30 '22 at 20:49
  • Using `localeCompare` with for example `1. Defender, 2. Defender, 10. Defender` will get you `1 > 10 > 2`. Be warned. – MrUpsidown May 30 '22 at 20:52
  • Thanks for pointing that out - if you have the string beginning with numbers larger than 9 and you want them sorted by the numerical value then you should do a numerical conversion before – oyophant May 30 '22 at 20:55
0

You are trying to perform a mathematical operation with two strings ('2. Defender' vs. '4. Forward').
You can just nest the same comparison you make for a[1] vs. b[1] as below:

let array = [
  ['ONE1', 5, '2. Defender', 'FALSE', 'TRUE', 'FALSE', 'undefined'],
  ['TWO2', 5, '4. Forward', 'TRUE', 'TRUE', 'FALSE', 'undefined'],
  ['THR3', 5, '2. Defender', 'TRUE', 'TRUE', 'FALSE', 'undefined'],
  ['FOR4', 4, '4. Forward', 'FALSE', 'TRUE', 'FALSE', 'undefined'],
  ['FIV5', 3, '5. Midfielder', 'FALSE', 'FALSE', 'FALSE', 'undefined']
]
array.sort(function(a, b) {
  if (a[1] === b[1]) {
    // Price is only important when cities are the same
    if (a[2] === b[2]) {
      //return 0;
      /* 
        or nest another comparison here and as many times as needed 
        within each child `a[n]===b[n]` block
       */
      if (a[3] === b[3]) {
        return 0; // or compare yet another col
      }
      return a[3] < b[3] ? 1 : -1;
    }

    return a[2] < b[2] ? 1 : -1;
  }

  return a[1] < b[1] ? 1 : -1;
})

array.forEach((p) => {
  console.log(p[0])
})

Otherwise you need to get the integer value of those strings to be able to do the math. You can use parseInt() or assign an explicit value according to your logic for each sorting column as below:

let array = [
  ['ONE1', 5, '2. Defender', 'FALSE', 'TRUE', 'FALSE', 'undefined'],
  ['TWO2', 5, '4. Forward', 'TRUE', 'TRUE', 'FALSE', 'undefined'],
  ['THR3', 5, '2. Defender', 'TRUE', 'TRUE', 'FALSE', 'undefined'],
  ['FOR4', 4, '4. Forward', 'FALSE', 'TRUE', 'FALSE', 'undefined'],
  ['FIV5', 3, '5. Midfielder', 'FALSE', 'FALSE', 'FALSE', 'undefined']
]
array.sort(function(a, b) {
  if (a[1] === b[1]) {
    // Price is only important when cities are the same
    let c = parseInt(a[2]);
    let d = parseInt(b[2]);
    if (c === d) {
      // the string 'TRUE' before 'FALSE', '' or null 
      let e = (a[3] === 'TRUE') ? 1 : 0;
      let f = (b[3] === 'TRUE') ? 1 : 0;

      return f - e;
    }

    return d - c;
  }

  return a[1] < b[1] ? 1 : -1;
})

array.forEach((p) => {
  console.log(...p)
})
Arleigh Hix
  • 9,990
  • 1
  • 14
  • 31