JavaScript array.sort with multiple values ​​(strings and numbers)

I would like to sort the array subject (string, alphabetically), then level (int, ascending), then name (string, alphabetically). I've found many other threads on SO, but I haven't found any of the multiple variable types. I thought I had it, but it doesn't sort correctly.

Sort function:

scipads.sort(function (a, b) {
    if (a.subject != b.subject)
        return a.subject < b.subject;
    if (a.level != b.level)
        return a.level - b.level;
    return a.name < b.name;
});

      

Array:

var scipads = [{
        "name": "L2 Physics Externals",
        "level": 2,
        "subject": "physics",
    }, {
        "name": "L2 Physics Internals",
        "level": 2,
        "subject": "physics",
    }, {
        "name": "L2 Chem Externals",
        "level": 2,
        "subject": "chemistry",
    }, {
        "name": "L2 Chem Internals",
        "level": 2,
        "subject": "chemistry",
    }, {
        "name": "L2 Bio Internals",
        "level": 2,
        "subject": "biology",
    }, {
        "name": "L2 Bio Externals",
        "level": 2,
        "subject": "biology",
    }, {
        "name": "L1 Electricity & Magnetism",
        "level": 1,
        "subject": "physics",
    }, {
        "name": "L1 Wave Behaviour",
        "level": 1,
        "subject": "physics",
    }, {
        "name": "L1 Heat",
        "level": 1,
        "subject": "physics",
    }, {
        "name": "L1 Carbon Chemistry",
        "level": 1,
        "subject": "chemistry",
    }, {
        "name": "L1 Selected Elements",
        "level": 1,
        "subject": "chemistry",
    }, {
        "name": "L1 Chemical Reactions",
        "level": 1,
        "subject": "chemistry",
    },
];

      

How can I sort by topic, then level, and then name?

+3


source to share


5 answers


Use localeCompare

to compare strings



var scipads=[{name:"L2 Physics Externals",level:2,subject:"physics"},{name:"L2 Physics Internals",level:2,subject:"physics"},{name:"L2 Chem Externals",level:2,subject:"chemistry"},{name:"L2 Chem Internals",level:2,subject:"chemistry"},{name:"L2 Bio Internals",level:2,subject:"biology"},{name:"L2 Bio Externals",level:2,subject:"biology"},{name:"L1 Electricity & Magnetism",level:1,subject:"physics"},{name:"L1 Wave Behaviour",level:1,subject:"physics"},{name:"L1 Heat",level:1,subject:"physics"},{name:"L1 Carbon Chemistry",level:1,subject:"chemistry"},{name:"L1 Selected Elements",level:1,subject:"chemistry"},{name:"L1 Chemical Reactions",level:1,subject:"chemistry"}];

scipads.sort(function(a, b) {
  if (a.subject != b.subject)
    return a.subject.localeCompare(b.subject);
  else if (a.level != b.level)
    return a.level - b.level;
  return a.name.localeCompare(b.name);
});

console.log(scipads);
      

Run codeHide result


+1


source


The comparison should return an integer . Here's an example:



scipads.sort((a, b) => {
    if (a.subject != b.subject) { 
        return a.subject < b.subject ? -1 : 1; 
    }
    if (a.level != b.level) { 
        return a.level - b.level; 
    }
    return a.name < b.name ? -1 : 1;
})

      

+2


source


The sort function of the sort is close, but not quite. You must return -1 for less than, 0 for equal, and 1 for greater than. See here for documentation.

Example: change return a.subject < b.subject

toreturn a.subject < b.subject ? -1 : 1;

+1


source


My solution, compare the topic first, then compare the level

var scipads=[{name:"L2 Physics Externals",level:2,subject:"physics"},{name:"L2 Physics Internals",level:2,subject:"physics"},{name:"L2 Chem Externals",level:2,subject:"chemistry"},{name:"L2 Chem Internals",level:2,subject:"chemistry"},{name:"L2 Bio Internals",level:2,subject:"biology"},{name:"L2 Bio Externals",level:2,subject:"biology"},{name:"L1 Electricity & Magnetism",level:1,subject:"physics"},{name:"L1 Wave Behaviour",level:1,subject:"physics"},{name:"L1 Heat",level:1,subject:"physics"},{name:"L1 Carbon Chemistry",level:1,subject:"chemistry"},{name:"L1 Selected Elements",level:1,subject:"chemistry"},{name:"L1 Chemical Reactions",level:1,subject:"chemistry"}];

// sort by subject, then level, then name
var res = scipads.sort((a, b) => {
  if (a.subject > b.subject) {
    return 1;
  } else if (a.subject < b.subject) {
    return -1;
  } else if ( a.level > b.level){
    return 1;
  } else if (a.level < b.level) {
    return -1;
  } else if (a.name > b.name) {
    return 1;
  } else if (a.name < b.name) {
    return -1;
  }
  return 0;
});


console.log(res)
      

Run codeHide result


0


source


To compare a string, you must use string.localeCompare

. Alternatively, you can try to create an array with a priority list and iterate over it to sort.

var scipads=[{name:"L2 Physics Externals",level:2,subject:"physics"},{name:"L2 Physics Internals",level:2,subject:"physics"},{name:"L2 Chem Externals",level:2,subject:"chemistry"},{name:"L2 Chem Internals",level:2,subject:"chemistry"},{name:"L2 Bio Internals",level:2,subject:"biology"},{name:"L2 Bio Externals",level:2,subject:"biology"},{name:"L1 Electricity & Magnetism",level:1,subject:"physics"},{name:"L1 Wave Behaviour",level:1,subject:"physics"},{name:"L1 Heat",level:1,subject:"physics"},{name:"L1 Carbon Chemistry",level:1,subject:"chemistry"},{name:"L1 Selected Elements",level:1,subject:"chemistry"},{name:"L1 Chemical Reactions",level:1,subject:"chemistry"}];

var priority = ["subject", "level", "name"]

scipads.sort(function(a,b){
  var val = 0;
  priority.some(function(k){
    val = compare(a,b,k);
    return val !== 0;
  });
})

function compare(a,b,k){
  switch(typeof a[k]){
    case "string": return a[k].localeCompare(b[k]);
    case "number": return a[k] - b[k]
  }
}

console.log(scipads)
      

Run codeHide result


0


source







All Articles