I have an array and I am sorting it but I need to sort everything except one element of my array.
My array is:
var Comparison = [
{key: \"None\", val
Not fancy, but a pretty straightforward way of doing this is to just remove the special element, sort the array, and insert the special to whatever index you want.
var Comparison = [{ key: "None", value: "None" }, { key: "Geographical Area",value: "Geographical_Area" }, { key: "Forests", value: "Forests" }, { key: "Barren Unculturable Land", value: "Barren_Unculturable_Land" }, { key: "Land put to Non agricultural use", value: "Land_put_to_Non_agricultural_use" }, { key: "Land Area", value: "Land_Area" }, { key: "Water Area", value: "Water_Area" }, { key: "Culturable Waste", value: "Culturable_Waste" }, { key: "Permanent Pastures", value: "Permanent_Pastures" }, { key: "Land under Tree Crops", value: "Land_under_Tree_Crops" }, { key: "Fallow Land excl Current Fallow", value: "Fallow_Land_excl_Current_Fallow" }, { key: "Current Fallow", value: "Current_Fallow" }, { key: "Total Unculturable Land", value: "Total_Unculturable_Land" }, { key: "Net Sown Area", value: "Net_Sown_Area" }, { key: "Gross Sown Area", value: "Gross_Sown_Area" }, { key: "Cropping Intensity", value: "Cropping_Intensity" },];
const idx = Comparison.findIndex(a => a.key === 'None');
const none = Comparison.splice(idx, 1);
Comparison.sort((a, b) => a.key.localeCompare(b.key));
Comparison.splice(0,0, none[0]);
console.log(Comparison);
To avoid no special or multiple special element issues:
var Comparison = [{ key: "None", value: "None" }, { key: "Geographical Area",value: "Geographical_Area" }, { key: "Forests", value: "Forests" }, { key: "Barren Unculturable Land", value: "Barren_Unculturable_Land" }, { key: "Land put to Non agricultural use", value: "Land_put_to_Non_agricultural_use" }, { key: "Land Area", value: "Land_Area" }, { key: "Water Area", value: "Water_Area" }, { key: "Culturable Waste", value: "Culturable_Waste" }, { key: "Permanent Pastures", value: "Permanent_Pastures" }, { key: "Land under Tree Crops", value: "Land_under_Tree_Crops" }, { key: "Fallow Land excl Current Fallow", value: "Fallow_Land_excl_Current_Fallow" }, { key: "Current Fallow", value: "Current_Fallow" }, { key: "Total Unculturable Land", value: "Total_Unculturable_Land" }, { key: "Net Sown Area", value: "Net_Sown_Area" }, { key: "Gross Sown Area", value: "Gross_Sown_Area" }, { key: "Cropping Intensity", value: "Cropping_Intensity" },];
const obj = Comparison.reduce((acc, a) => {
if (a.key === 'None') {
acc.f.push(a);
} else {
const idx = acc.s.findIndex(b => b.key.localeCompare(a.key) > 0);
acc.s.splice(idx === -1 ? acc.s.length : idx, 0, a);
}
return acc;
}, { f: [], s: [] });
const res = obj.f.concat(obj.s);
console.log(res);
There might be a better approach, but this should work:
Filter the special value out of your array.
Sort your array without the special value.
Insert the special value back in the array.
For a good working example, see @Johan Wentholt's answer!
The <Array>.sort
function takes a callback as an argument. This callback will be passed two values. The job of the callback is to determine which one is bigger. It does this by returning a numeric value.
Let's say the arguments passed to your callback are called a
and b
. I have bolded the values your callback should return for each case
a < b
Less than 0a > b
Greater than 0a = b
Equal to 0This is easy to remember because, for numerical values, you can use a - b
to get a desired return value.
Now, despite most callbacks passed to .sort
are very small, it is possible to pass in very complicated functions to suit your need. In this case,
a.key
is None, a < b
b.key
is None, b < a
We could take advantage of the return
statement exiting once it's called. So, let's implement this function bullet-by-bullet.
To make our code Super Good, let's return "0" when the two values are equal (even when those two values have keys of "None")
Comparison.sort(function(a, b) {
// Our extra code
if(a.key === b.key) return 0; // Zero (a = b)
if(a.key === "None") return -1; // Negative (a < b)
if(b.key === "None") return 1; // Positive (b < a)
// Old sort
if(a.key < b.key) return -1;
if(b.key < a.key) return 1;
})
There are ways to make that solution shorter (and, perhaps, more readable) -- which is important when code is doing simple tasks.
The first thing to note is that the final line, if(b.key < a.key) return -1
could be shortened to return -1;
. This is because if a.key < b.key
or b.key = a.key
we would've returned on an earlier line.
The second thing to note is that using ES6 syntax (which might not be compatible with older browsers, particularly regarding Internet Explorer), we can use arrow function notation for the callback.
function(a, b) {}
could become (a, b) => {}
The third thing to note is that we can convert the below block of code
if(a.key < b.key) return -1;
if(b.key < a.key) return 1;
into
return (b.key < a.key) - (a.key < b.key)
That's because true
is treated as 1
, and false
as 0
when regarding subtraction. true - false
is 1 - 0
is 1
, false - true
is 0 - 1
is -1
, and 0 - 0
is 0
. There will never be a situation where true - true
occurs.
var Comparison_sort = this.Comparison.sort(function (a, b) {
if(a.key == b.key) return 0;
if (a.key == 'None') return -1;
if (b.key == 'None') return 1;
if (a.key < b.key)
return -1;
if (a.key > b.key)
return 1;
return 0;
});
tells "do a regular sort, except if the key is none which means it must go first."
You can use reduce
to achieve the desired output:
var Comparison = [{key:"Geographical Area", value:"Geographical_Area"}, {key:"Forests", value:"Forests"}, {key:"Barren Unculturable Land", value:"Barren_Unculturable_Land"}, {key: "None", value: "None"}, {key:"Land put to Non agricultural use", value:"Land_put_to_Non_agricultural_use"}, {key:"Land Area", value:"Land_Area"}, {key:"Water Area", value:"Water_Area"}, {key:"Culturable Waste", value:"Culturable_Waste"}, {key:"Permanent Pastures", value:"Permanent_Pastures"}, {key:"Land under Tree Crops", value:"Land_under_Tree_Crops"}, {key:"Fallow Land excl Current Fallow", value:"Fallow_Land_excl_Current_Fallow"}, {key:"Current Fallow", value:"Current_Fallow"}, {key:"Total Unculturable Land", value:"Total_Unculturable_Land"}, {key:"Net Sown Area", value:"Net_Sown_Area"}, {key:"Gross Sown Area", value:"Gross_Sown_Area"}, {key:"Cropping Intensity", value:"Cropping_Intensity"},]
var Comparison_sort = Comparison
.sort((a, b) => a.key.localeCompare(b.key))
.reduce((acc, e) => {
e.key === 'None' ? acc.unshift(e) : acc.push(e);
return acc;
}, []);
console.log(Comparison_sort);
Sort using reduce
version-2:
let comparison = [{key: "None", value: "None"}, {key: "Geographical Area", value: "Geographical_Area"}, {key: "Forests", value: "Forests"}, {key: "Barren Unculturable Land", value: "Barren_Unculturable_Land"}, {key: "Land put to Non agricultural use", value: "Land_put_to_Non_agricultural_use"}, {key: "Land Area", value: "Land_Area"}, {key: "Water Area", value: "Water_Area"}, {key: "Culturable Waste", value: "Culturable_Waste"}, {key: "Permanent Pastures", value: "Permanent_Pastures"}, {key: "Land under Tree Crops", value: "Land_under_Tree_Crops"}, {key: "Fallow Land excl Current Fallow", value: "Fallow_Land_excl_Current_Fallow"}, {key: "Current Fallow", value: "Current_Fallow"}, {key: "Total Unculturable Land", value: "Total_Unculturable_Land"}, {key: "Net Sown Area", value: "Net_Sown_Area"}, {key: "Gross Sown Area", value: "Gross_Sown_Area"}, {key: "Cropping Intensity", value: "Cropping_Intensity"}];
var {Comparison_sort} = comparison.reduce((acc, obj, idx, arr) => {
obj.key === 'None' ? acc['first'].push(obj) : acc['last'].push(obj)
if (idx === arr.length - 1) (acc['last'].sort((a, b) => a.key.localeCompare(b.key)), acc['Comparison_sort'] = [...acc['first'], ...acc['last']])
return acc
}, {first: [], last: [], Comparison_sort: []})
console.log(Comparison_sort);
Just add a check at the beginning. If it's the none object then move it to the front without performing the checks.
var Comparison_sort = this.Comparison.sort(function (a, b) {
if (a.key == "None" && a.value == "None")
return -1;
if (b.key == "None" && b.value == "None")
return 1;
if (a.key < b.key)
return -1;
if (a.key > b.key)
return 1;
return 0;
});