Sort an array so that null values always come last

前端 未结 8 2204
轮回少年
轮回少年 2020-11-28 05:46

I need to sort an array of strings, but I need it so that null is always last. For example, the array:

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

When

相关标签:
8条回答
  • 2020-11-28 06:24

    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)

    0 讨论(0)
  • 2020-11-28 06:29

    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]

    0 讨论(0)
  • 2020-11-28 06:34

    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);
        }
    });
    
    0 讨论(0)
  • 2020-11-28 06:37

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

    0 讨论(0)
  • 2020-11-28 06:38

    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, just swap a and b in the direct comparison:

    arr.sort(function(a, b) {
        return (a===null)-(b===null) || -(a>b)||+(a<b);
    });
    
    0 讨论(0)
  • 2020-11-28 06:45

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

    0 讨论(0)
提交回复
热议问题