javascript排序混合字符串和空值的数组

时间:2010-02-24 18:43:03

标签: javascript arrays sorting

当soritng由混合字符串,空值和零组成的数组时,我得到的结果不能正确检测,null值似乎被排序为好像它们是'null'字符串。 我这样做了(在FireFox上测试过):

var arr1 = arr2 = [null, "b", "c", "d", null, "e", 0, "g", null, 0, "h", "i", "l", "m", "n", "o", "p", "ne", "nur", "nimbus"];

document.write("SORTED ARRAY:<br>");
arr1.sort();
arr1.forEach(function(val){document.write(val + "; ")});

结果是:

SORTED ARRAY: 0; 0; b; C; d; Ë; G; H;一世;升;米; N; NE;雨云;空值;空值;空值;努尔; O;磷;

您是否知道如何在排序数组期间将空值视为空字符串,以便它们在排序的arry中与零一起显示为第1位。

谢谢!

11 个答案:

答案 0 :(得分:13)

这将通过将所有内容转换为字符串(特别是将null转换为空字符串)并允许JavaScript的内置字符串比较来完成所需的工作:

arr2.sort( function(a, b) 
{
    /* 
       We avoid reuse of arguments variables in a sort
       comparison function because of a bug in IE <= 8.
       See http://www.zachleat.com/web/array-sort/
    */
    var va = (a === null) ? "" : "" + a,
        vb = (b === null) ? "" : "" + b;

    return va > vb ? 1 : ( va === vb ? 0 : -1 );
} );

答案 1 :(得分:7)

[null, "b", "c", "d", null, "e", 0, "g", null, 0, "h", "i", "l", "m", "n", "o", "p", "ne", "nur", "nimbus"].sort(function (a,b) { 
   return a === null ? -1 : b === null ? 1 : a.toString().localeCompare(b);
});

答案 2 :(得分:4)

我遇到了这个线程,寻找类似的快速和肮脏的答案,但它没有触及我实际需要的东西。 “如何处理空值”,将它们浮动到顶部或底部等等。这就是我提出的:

    var list = [0, -1, 1, -1, 0, null, 1];

var sorter = function(direction){

    // returns a sort function which treats `null` as a special case, either 'always higher' (1)
    // or 'always lower' (-1)

    direction = direction || 1;
    var up = direction > 0;

    return function(a, b){

        var r = -1,
            aa = a == null ? undefined : a,
            bb = b == null ? undefined : b,
            careabout = up ? aa : bb
        ;

        if(aa == bb){
            r = 0;
        }else if(aa > bb || careabout == undefined){
            r = 1
        }
        return r;

    }

}

var higher = [].concat(list.sort(sorter(1)));    
var lower = [].concat(list.sort(sorter(-1)));

console.log(lower[0] === null, lower);
console.log(higher[higher.length - 1] === null, higher);

// then, something that sorts something in a direction can use that direction to
// determine where the nulls end up. `list` above ranged from negative-one to one, 
// with mixed zero and null values in between. If we want to view that list 
// from highest value to descending, we'd want the nulls to be treated as 
// 'always lower' so they appear at the end of the list.
// If we wanted to view the list from lowest value to highest value we'd want the
// nulls to be treated as `higher-than-anything` so they would appear at the bottom
// list.

var sortThisArray = function(arr, direction){
    var s = sorter(direction);
    return arr.sort(function(a,b){
       return direction * s(a,b) 
    });
}

console.log(sortThisArray(list, 1));
console.log(sortThisArray(list, -1));

答案 3 :(得分:3)

我还无法评论答案,但我想分享我的问题以防其他人使用Tims解决方案。

蒂姆的解决方案效果很好。但是......它会间歇性地抛出“预期的数字”错误。完全随机。

此链接解释了问题以及为我解决问题的解决方法......

http://www.zachleat.com/web/array-sort/

希望这可以节省一些人浪费时间调试/谷歌搜索!

答案 4 :(得分:3)

我无法在@ robert的评论中添加评论,但这是@ robert的扩展,以增加对布尔的支持:

[null, "b", "c", "d", null, "e", 0, undefined, "g", null, 0, "h", "i", true, "l", "m", undefined, "n", "o", "p", false, "ne", "nur", "nimbus"].sort(function (a,b) { 
    if (a === b) { return 0; }
    if (a === null) {
        return -1;
    } else if (b === null) {
        return 1;
    } else if (typeof a === 'string') {
        return a.localeCompare(b);
    } else if (typeof a === 'number' || typeof a === 'boolean') {
        if (a < b) return -1;
        if (a > b) return 1;
    }
    return 0;
});

另外,根据JS规范,undefined总是被引导到数组的末尾......

答案 5 :(得分:1)

使用以这种方式处理空值的自定义排序函数。

arr1.sort(function(a, b) {
    if (a===null) a='';
    if (b===null) b='';

    if (''+a < ''+b) return -1;
    if (''+a > ''+b) return  1;

    return 0;
});

答案 6 :(得分:0)

我建议对具有混合值(数字,字符串,空值,未定义值)的数组进行升序排序。

const arr = [null, 'b46', '+', 'Яромир Ягр', '76region', 2, 9999999, 'Эркер', '', 0, 3, 33, 765, '366', '77rus', 'ааэ', null, null, '200', undefined, 'ААА', '1', '40', 88, 'cat', undefined, 'apple', 4, '55555', 777, 12, 6, 0, '55', 8, null, undefined, '  Жу', 'жа', 'bbbb', '    Xz', '  Z', 'aa', undefined];

const sortAsc = (arr) => {
  const undefinedAndNulls = arr.filter(val => val === null || val === undefined);
  const numbers = arr.filter(val => !isNaN(val) && val !== null);
  const sortedNumbers = numbers.sort((a, b) => a - b);
  const rest = arr.filter(val => val && isNaN(val));
  const sortedRest = rest.sort((a, b) => {
    const val1 = a || '';
    const val2 = b || '';
    const valueA = val1.toString().trimLeft();
    const valueB = val2.toString().trimLeft();
    return valueA.localeCompare(valueB);
  });
  return [...undefinedAndNulls, ...sortedNumbers, ...sortedRest];
};

结果:

[null, null, null, undefined, undefined, null, undefined, undefined, '', 0, 0, '1', 2, 3, 4, 6, 8, 12, 33, '40', '55', 88, '200', '366', 765, 777, '55555', 9999999, '+', '76region', '77rus', 'aa', 'apple', 'b46', 'bbbb', 'cat', '    Xz', '  Z', 'ААА', 'ааэ', 'жа', '  Жу', 'Эркер', 'Яромир Ягр'];

答案 7 :(得分:0)

由于我一直在使用不同的用例来对诸如null和undefined之类的东西进行排序,因此我创建了以下函数,以使用一组选项来创建比较器。如果对其他人有用,请在此处添加。

请注意,此函数当前无法处理NaN和其他情况,例如混合类型,但是可以很容易地将它们添加为选项。

用法示例:

array.sort(createComparator({
   property: 'path.to.property',
   direction: 'desc',
   sortNulls: 'top',
   caseSensitive: true,
});

array.sort(createComparator({
   accessor: value => value.date.valueOf(),
   direction: 'desc',
   sortNulls: 'top',
   caseSensitive: true,
});

代码是:

import get from 'lodash/get';

/**
 * Creates a comparator function for sorting given a set of options.
 *
 * @param {String}   options.property       
 *                   The path to the property to sort by
 *                   
 * @param {Function} options.accessor       
 *                   The function used to calculate the property to sort by. Takes the 
 *                   item being sorted and returns the value to use for the sorting 
 *                   comparison
 *                   
 * @param {String}   options.direction      
 *                   The direction of sort: `asc` or `desc`. Defaults to `asc`
 *                   
 * @param {String}   options.sortNulls      
 *                   Where null values should be sorted: `top` or `bottom`. Defaults 
 *                   to `top`
 *                   
 * @param {String}   options.sortUndefineds 
 *                   Where undefined values should be sorted: `top` or `bottom`. 
 *                   Defaults to the value of `sortNulls`
 *                   
 * @param {boolean}  options.caseSensitive  
 *                   Whether to compare strings with the case of letters affecting 
 *                   the sort. Defaults to `false`
 *
 * @return {Function} A comparator function that can be used with `Array.sort` to 
 *                    sort an array
 */
function createComparator({
  property,
  accessor,
  direction = 'asc',
  sortNulls = 'top',
  sortUndefineds,
  caseSensitive = false,
}) {
  const topNulls = sortNulls === 'top';

  // Convert binary parameters to boolean to avoid doing it for each comparison
  return advancedComparator.bind(null, {
    accessor: property ? value => get(value, property) : accessor,
    desc: direction === 'desc' ? -1 : 1,
    topNulls,
    topUndefineds: sortUndefineds != null ? sortUndefineds === 'top' : topNulls,
    caseSensitive,
  });
}

function advancedComparator(options, a, b) {
  const { accessor, desc, topNulls, topUndefineds, caseSensitive } = options;

  a = accessor ? accessor(a) : a;
  b = accessor ? accessor(b) : b;

  if (a === null) {
    return b === null ? 0 : (topNulls ? -1 : 1);
  } else if (b === null) {
    return (topNulls ? 1 : -1);
  }

  if (typeof a === 'undefined') {
    return typeof b === 'undefined' ? 0 : (topUndefineds ? -1 : 1);
  } else if (typeof b === 'undefined') {
    return (topUndefineds ? 1 : -1);
  }

  if (!caseSensitive) {
    a = typeof a === 'string' ? a.toLowerCase() : a;
    b = typeof b === 'string' ? b.toLowerCase() : b;
  }

  if (typeof a === 'string' && typeof b === 'string') {
    return a.localeCompare(b);
  }

  if (a > b) { return 1 * desc; }
  if (a < b) { return -1 * desc; }

  return 0;
}

答案 8 :(得分:0)

我们可以用最简单的方法完成

sort: (a, b) => {
        a = a.name || '';
        b = b.name || '';
        return a.localeCompare(b);
    }

答案 9 :(得分:-1)

浏览器正在执行null.toString();因为null是一个Object,所以这几乎是Object.toString()...它将返回“null”

传入一个参数进行排序,作为比较函数[如果函数返回的值大于0,则b的排序低于a]

功能基本上是:

comparisonFunc = function(a, b)
{
 if((a === null) && (b === null)) return 0; //they're both null and equal
 else if((a === null) && (b != null)) return -1; //move a downwards
 else if((a != null) && (b === null)) return 1; //move b downwards
 else{
  //Lexicographical sorting goes here
 }
}
set.sort(comparisonFunc);

答案 10 :(得分:-1)

您可以传递排序函数

array.sort(sortfunction)

其中sortfunction执行您需要的比较(使用空值的常规排序大于其他值)