对数组进行排序,以便空值始终排在最后

IT技术 javascript
2021-02-21 06:17:58

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

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

当升序排序[a, b, d, null, null]时,我需要像[d, b, a, null, null].

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

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

6个回答

检查.sort()并使用自定义排序进行操作。例子

function alphabetically(ascending) {

  return function (a, b) {

    // equal items sort equally
    if (a === b) {
        return 0;
    }
    // nulls sort after anything else
    else if (a === null) {
        return 1;
    }
    else if (b === null) {
        return -1;
    }
    // otherwise, if we're ascending, lowest sorts first
    else if (ascending) {
        return a < b ? -1 : 1;
    }
    // if descending, highest sorts first
    else { 
        return a < b ? 1 : -1;
    }

  };

}

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

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

@JeffreyWen 基本上你给“sort()”一个函数,该函数为每对元素运行。例如运行这个[1,2,3,4,5,6,7].sort(function(a,b){ console.log('comparing pair:', a,b); return -1; })然后 [1,2,3,4,5,6,7].sort(function(a,b){ console.log('comparing pair:', a,b); return 1; }) 对于每一对,你可以返回一个负数或正数,以改变或不改变对的顺序。我希望这是有道理的。试验它并使用 console.log 来查看该函数的作用。
2021-04-16 06:17:58
谁能解释为什么我们为 a 发送 1 而为 b 发送 -1?if(a === null) { 返回 1; } else if(b === null){ return -1; }
2021-04-22 06:17:58
@AntouanK 如果你想先放空你怎么做??
2021-04-24 06:17:58
@BartRömgens 或其他任何人,我仍然无法理解文档中的那一行。你能不能再详细一点来帮助我?
2021-05-06 06:17:58
@prgmrDev 请参阅排序文档:“如果 compareFunction(a, b) 小于 0,则将 a 排序为低于 b 的索引(即 a 先出现)。”
2021-05-08 06:17:58

使用区null分值的自定义比较函数

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

对于非空值的降序,只需交换ab直接比较:

arr.sort(function(a, b) {
    return (a===null)-(b===null) || -(a>b)||+(a<b);
});
在按升序对日期进行排序时,使用此技术将空日期发送到列表底部。高明的解决方案,谢谢!
2021-04-15 06:17:58
@Bergi - 对不起,你当然是对的。我对自己的用例感到困惑!我需要先放置空值,但是在阅读您的评论时,我意识到您正在讨论非空值的降序。我首先使用 'b===null - a === null...' 实现了非空。为我的笨拙道歉,并感谢您的方便回答!
2021-04-30 06:17:58
请注意解释在 1) 其中一个为空 2) 都不为空的情况下这是如何工作的?
2021-05-04 06:17:58
@AbhishekEkaanth 您可以在空比较中交换abreturn (b===null)-(a===null) || …
2021-05-04 06:17:58
@cegprakash 如果其中一个是null,则(a===null)-(b===null)表达式将计算为1or -1(布尔值的减法被强制为一个数字),当两者都不是时null,它将计算为0并且||表达式的第二部分将生效。
2021-05-09 06:17:58

上升

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

降序

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

(对于降序,如果数组中没有负值,我建议使用 0 而不是 -Infinity)

^ 这是固定的
2021-04-25 06:17:58
这不会正确区分null0虽然。你应该== null在你的三元状态。
2021-05-15 06:17:58

最简单的方法是先处理null,然后根据所需顺序处理非空情况:

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]

如果您需要对数字进行自然排序或由Collator(包括速度增强和尊重语言环境)提供的任何选项,请尝试这种方法,基于 Paul Roub 的解决方案,稍微清理一下。我们几乎总是使用数字排序,因此默认...

如果您不是 Typescript 粉丝,只需去掉:type规格或从代码片段中复制即可。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collat​​or

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

像这样使用它。

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

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

您可以修改工厂方法以采用整理器,以获得更大的灵活性。

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

工作片段

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