Using logical OR operator inside a loop to sort an array

Tags: ,



I have an array like this:

var planets_info = [
    {
    "name": "Mercury",
    "size": 120,
    "color": "gray",
  },
  {
    "name": "Earth",
    "size": 100,
    "color": "blue",
  },
  {
    "name": "Mars",
    "size": 200,
    "color": "red",
  }
];

That I am trying to sort based on name and size or color. This is defined like this:

var sorts = "size,name"; // or size, name, color dynamic value

I can do sorting like this:

planets_info = planets_info.sort( function(a, b){
        return a.size - b.size || a.color - b.color;
        //  or
        // return a.size - b.size || a.color - b.color || a.name - b.name;

        //  or
        // a.color - b.color || a.name - b.name;

});

But I dont know how to modify the sort so it sorts based on the values from var sorts – so a.size - b.size || a.color - b.color; will be dynamic based on the values from sorts – it can be based on name,size or name,size,color which will be added by || :

var sorts = "size,name";
sorts = sorts.split(',');

sorts.forEach(element=> {
    console.log("sort " + element);
});

Answer

See Dynamically access object property using variable

You can access keys using a variable by using the bracket notation:

const obj = {
  "name": "Mercury",
  "size": 120,
  "color": "gray",
};

const key = "name";

console.log(obj[key]);

Furthermore, if your string is always comma separated, you can call String#split() to convert it into keys:

const sorts = "name,size,color";

const keys = sorts.split(",");

console.log(keys);

const obj = {
  "name": "Mercury",
  "size": 120,
  "color": "gray",
};

console.log(obj[keys[0]]);
console.log(obj[keys[1]]);
console.log(obj[keys[2]]);

Before we continue, I have to point out that subtracting two values only works if you’re sorting numbers, not if you’re sorting strings. For example

console.log("Mars" - "Mercury");
console.log("red" - "blue");

If you want a more universal sorting, you can use the relation comparison operators < and > that works on numbers, strings, and some objects like dates. Keep in mind that you have to return three values, not just true and false. So with this in mind, it’s easy to create a generic comparison function:

const compare = (a, b) => {
  if (a < b)
    return -1;
  
  if (a > b)
    return 1;
    
  return 0;
}
                                         // sort order:
console.log(compare("Mars", "Mercury")); // Mars, Mercury
console.log(compare("red", "blue"));     // blue, red
console.log(compare(120, 100));          // 100, 120

console.log(compare(                     // 7th of January, 11th of January
  new Date("2021-01-07"),
  new Date("2021-01-11")
));

Now with this, alongside Array#reduce() you can achieve dynamic sorting:

const compare = (a, b) => {
  if (a < b)
    return -1;
  
  if (a > b)
    return 1;
    
  return 0;
}

function sorter(arr, sorts) {
  const keys = sorts.split(",");
  return arr.sort((a, b) => 
    keys.reduce((acc, key) => acc || compare(a[key], b[key]), 0)
  );
}

var planets_info = [
  { "name": "Mercury", "size": 120, "color": "gray", },
  { "name": "Earth"  , "size": 100, "color": "blue", },
  { "name": "Mars"   , "size": 200, "color": "red" , }
];

const result1 = sorter(
  [
    { "name": "Mercury", "size": 120, "color": "gray", },
    { "name": "Earth"  , "size": 100, "color": "blue", },
    { "name": "Mars"   , "size": 200, "color": "red" , }
  ],
  "name,size,color"
);

console.log('sorted by "name,size,color":', result1);


const result2 = sorter(
  [
    { "name": "Mercury", "size": 120, "color": "gray", },
    { "name": "Earth"  , "size": 100, "color": "blue", },
    { "name": "Mars"   , "size": 200, "color": "red" , }
  ],
  "size,name,color"
);

console.log('sorted by "name,size,color":', result2);


const result3 = sorter(
  [
    { "name": "Mercury", "size": 120, "color": "gray", },
    { "name": "Earth"  , "size": 100, "color": "blue", },
    { "name": "Mars"   , "size": 200, "color": "red" , }
  ],
  "color,name,size"
);

console.log('sorted by "name,size,color":', result3);


const result4 = sorter(
  [
    { "name": "Earth", "size": 120, "color": "blue", },
    { "name": "Earth", "size": 100, "color": "blue", },
    { "name": "Earth", "size": 200, "color": "blue" , }
  ],
  "name,color,size"
);

console.log('three Earths sorted by "name,color,size":', result4);


Source: stackoverflow