Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
混合字符串和空值的javascript排序数组_Javascript_Arrays_Sorting - Fatal编程技术网

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

混合字符串和空值的javascript排序数组,javascript,arrays,sorting,Javascript,Arrays,Sorting,当对一个由字符串、空值和零组成的数组进行排序时,我得到的结果没有正确地表示出来,空值似乎被排序为“空”字符串。 我这样做了(在FireFox上测试): var arr1=arr2=[null,“b”,“c”,“d”,null,“e”,0,“g”,null,0,“h”,“i”,“l”,“m”,“n”,“o”,“p”,“ne”,“nur”,“nimbus”]; 写入(“排序数组:”; arr1.sort(); arr1.forEach(函数(val){document.write(val+“;”)}

当对一个由字符串、空值和零组成的数组进行排序时,我得到的结果没有正确地表示出来,空值似乎被排序为“空”字符串。 我这样做了(在FireFox上测试):

var arr1=arr2=[null,“b”,“c”,“d”,null,“e”,0,“g”,null,0,“h”,“i”,“l”,“m”,“n”,“o”,“p”,“ne”,“nur”,“nimbus”];
写入(“排序数组:
”; arr1.sort(); arr1.forEach(函数(val){document.write(val+“;”)});
结果是:

排序数组: 0; 0; BCDEGH我LMN氖;灵气;无效的无效的无效的努尔;o;p

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


谢谢

浏览器正在执行null.toString();因为null是一个对象,所以它实际上是一个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);

您可以将排序传递给sort函数

array.sort(sortfunction)

在sortfunction执行所需比较的地方(空值大于其他值的常规排序)

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

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;
});
arr1.sort(函数(a,b){
如果(a==null)a='';
如果(b==null)b='';
如果(“”+a<“”+b)返回-1;
如果(“”+a>“”+b)返回1;
返回0;
});

这将通过将所有内容转换为字符串(特别是将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 );
} );
arr2.sort(函数(a,b)
{
/* 
我们避免在排序中重复使用参数和变量
由于IE vb?1中的错误而导致的比较函数:(va===vb?0:-1);
} );

我还无法对答案发表评论,但我想与大家分享我的问题,以防其他人使用Tims解决方案

Tims解决方案非常有效。然而。。。它会间歇性地抛出一个“数字预期”错误。完全随机的

这个链接解释了这个问题,并为我解决了这个问题


希望这能节省我浪费在调试/谷歌搜索上的时间

我偶然发现了这条线索,想寻找一个类似的快速而肮脏的答案,但它没有触及我真正需要的东西。“如何处理空值”,将它们浮到顶部或底部,等等。这就是我想到的:

    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));

我还不能在@robert's的评论中添加评论,但是这里有一个@robert's的扩展来添加对布尔值的支持:

[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;
});
[null,“b”,“c”,“d”,null,“e”,0,未定义,“g”,null,0,“h”,“i”,true,“l”,“m”,未定义,“n”,“o”,“p”,false,“ne”,“nur”,“nimbus”]排序(函数(a,b){
如果(a==b){返回0;}
如果(a==null){
返回-1;
}else if(b==null){
返回1;
}else if(a的类型=='string'){
返回a.localeCompare(b);
}else if(typeof a=='number'| | typeof a=='boolean'){
如果(ab)返回1;
}
返回0;
});

另外,根据JS规范,未定义的数组总是被引导到数组的末尾…

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

结果:

[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', 'ААА', 'ааэ', 'жа', '  Жу', 'Эркер', 'Яромир Ягр'];

由于我一直在使用不同的用例对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;
}
从“lodash/get”导入get;
/**
*创建一个比较器函数,用于对给定的一组选项进行排序。
*
*@param{String}options.property
*要排序的属性的路径
*                   
*@param{Function}options.accessor
*用于计算排序依据的属性的函数。承担
*正在排序的项,并返回用于排序的值
*比较
*                   
*@param{String}options.direction
*排序方向:`asc`或`desc`。默认为“asc”`
*                   
*@param{String}options.sortNulls
*其中空值应排序为:`top`或`bottom`。默认值
*顶`
*                   
*@param{String}options.sortunedefineds
*未定义值应排序的位置:`top`或`bottom`。
*默认值为'sortNulls'`
*                   
*@param{boolean}options.caseSensitive
*是否将字符串与字母大小写进行比较
*那种。默认为“false”`
*
*@return{Function}一个比较器函数,可与'Array.sort'一起使用,以
*对数组排序
*/
函数比较器({
财产,,
访问器,
方向='asc',
sortNulls=‘顶部’,
不幸的是,
区分大小写=错误,
}) {
const topNulls=sortNulls=='top';
//将二进制参数转换为布尔值,以避免每次比较都这样做
返回advancedComparator.bind(null{
访问器:property?value=>get(value,property):访问器,
描述:方向=='desc'?-1:1,
topNulls,
topUndefineds:sortUndefineds!=null?sortUndefineds==='top':topNulls,
区分大小写,
});
}
功能高级比较器(选项a、b){
const{accessor,desc,topNulls,topnefineds,区分大小写}=options;
a=存取器?存取器(a):a;
b=存取器?存取器(b):b;
如果(a==null){
返回b==null?0:(topNulls?-1
[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', 'ААА', 'ааэ', 'жа', '  Жу', 'Эркер', 'Яромир Ягр'];
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;
}
sort: (a, b) => {
        a = a.name || '';
        b = b.name || '';
        return a.localeCompare(b);
    }