对数组进行排序,以便空值总是排在最后

我需要对一个字符串数组排序,但是我需要它使 null 总是最后一个。例如,数组:

var arr = [a, b, null, d, null]

升序排序时,我需要它像 [a, b, d, null, null]那样排序,降序排序时,我需要它像 [d, b, a, null, null]那样排序。

这可能吗? 我尝试了下面找到的解决方案,但它不完全是我所需要的。

如何比较字符串和数值(关于负值,空总是最后) ?

109521 次浏览

Check out .sort() and do it with custom sorting. Example

function alphabetically(ascending) {
return function (a, b) {
// equal items sort equally
if (a === b) {
return 0;
}


// nulls sort after anything else
if (a === null) {
return 1;
}
if (b === null) {
return -1;
}


// otherwise, if we're ascending, lowest sorts first
if (ascending) {
return a < b ? -1 : 1;
}


// if descending, highest sorts first
return a < b ? 1 : -1;
};
}






var arr = [null, "a", "z", null, "b"];


console.log(arr.sort(alphabetically(true)));
console.log(arr.sort(alphabetically(false)));

Use a custom compare function that discriminates against null values:

arr.sort(function(a, b) {
return (a===null)-(b===null) || +(a>b)||-(a<b);
});

For descending order of the non-null values, just swap a and b in the direct comparison:

arr.sort(function(a, b) {
return (a===null)-(b===null) || -(a>b)||+(a<b);
});

The simplest approach is to handle null first, then deal with non-null cases based on the desired order:

function sortnull(arr, ascending) {
// default to ascending
if (typeof(ascending) === "undefined")
ascending = true;


const multiplier = ascending ? 1 : -1;


const sorter = function(a, b) {
if (a === b)          // identical? return 0
return 0;
else if (a === null)  // a is null? last
return 1;
else if (b === null)  // b is null? last
return -1;
else                  // compare, negate if descending
return a.localeCompare(b) * multiplier;
}


return arr.sort(sorter);
}


const arr = ["a", "b", null, "d", null];


console.log(sortnull(arr));        // ascending   ["a", "b", "d", null, null]
console.log(sortnull(arr, true));  // ascending   ["a", "b", "d", null, null]
console.log(sortnull(arr, false)); // descending  ["d", "b", "a", null, null]

like this, note: this will only push the null's to the back

var arr = ["a", null, "b"];
var arrSor = [];
arr.forEach(function (el) {


if (el === null) {
arrSor.push(el);
} else {
arrSor.unshift(el);
}
});

Do it like:

        var arr = [a, b, null, d, null]


foreach ($arr as $key => $value) {
if($value == null)
unset($arr[$key]);
$arr[] = $value;


}
// rebuild array index
$arr = array_values($arr);


echo '<pre>';print_r($arr);die;

If you need natural sorting for numbers, or any of the options provided by Collator (including speed enhancements and respecting locale), try this approach, based off of Paul Roub's solution, cleaned up a bit. We almost always use numeric sorting, hence the defaults...

If you are not a Typescript fan, just strip off the :type specs or copy from the snippet.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator

const naturalCollator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
const alphabeticCollator = new Intl.Collator(undefined, {});


function nullSort(descending: boolean = false, alphabetic: boolean = false) {
return function (a: any, b: any): number {
if (a === b) {
return 0;
}
if (a === null) {
return 1;
}
if (b === null) {
return -1;
}


let ret
if (alphabetic) {
ret = alphabeticCollator.compare(a, b)
} else {
ret = naturalCollator.compare(a, b)
}
if (descending) {
ret = -ret
}
return ret
};
}

Use it like this.

// numeric, ascending (default)
myList.sort(nullSort());


// alphabetic, descending
myList.sort(nullSort(true, true));

You can modify the factory method to take a collator instead, for greater flexibility.

function nullSort(descending: boolean = false, collator: Collator = naturalCollator)

Working Snippet

const naturalCollator = new Intl.Collator(undefined, {
numeric: true,
sensitivity: 'base'
});
const alphabeticCollator = new Intl.Collator(undefined, {});


function nullSort(descending = false, alphabetic = false) {
return function(a, b) {
if (a === b) {
return 0;
}
if (a === null) {
return 1;
}
if (b === null) {
return -1;
}


let ret
if (alphabetic) {
ret = alphabeticCollator.compare(a, b)
} else {
ret = naturalCollator.compare(a, b)
}
if (descending) {
ret = -ret
}
return ret
};
}


const items = [null, 10, 1, 100, null, 'hello', .1, null]


console.log(items.sort(nullSort()));

Ascending

arr.sort((a, b) => (a != null ? a : Infinity) - (b != null ? b : Infinity))

Descending

arr.sort((a, b) => (b != null ? b : -Infinity) - (a != null ? a : -Infinity))

(For descending order if you don't have negative values in the array, I recommend to use 0 instead of -Infinity)

I am sorting objects with a custom index and this works for me. I am not wanting to change the original array and it is important to keep the null indexes where they are.

let sorted = [...array].sort((a, b) => {
if (!a || !b) return 0;
else return a.CustomIndex - b.CustomIndex;
});
function sortNumsAsc(arr) {
if(arr === null || arr === []) {
return [];
}
else {
return arr.sort(function(a,b){return a-b});
//return newarr;
}
}
console.log(sortNumsAs([801, 19, 4, 5, -4, 85]))