Массив сортировки javascript смешанных строк и нулевые значения

При сортировке массива, состоящего из комбинации строк, нулевых значений и нулей, я получаю результат не так, как выведенный, нулевые значения, похоже, сортируются так, как если бы они были "нулевыми" строками. Я сделал это (протестирован на 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 + "; ")});

И результат:

СОРТИРОВАННАЯ МАССА: 0; 0; б; с; д; е; г; час; я; л; м; п; пе; венчик; ноль; ноль; ноль; нур; о; п;

У вас есть идея, как заставить нулевое значение считаться пустой строкой во время сортировки массива, так что они появляются на первом месте в отсортированном массиве вместе с нулями.

Спасибо!

Ответ 1

Это сделает то, что вы хотите, преобразовывая все в строки (в частности, преобразуя нуль в пустую строку) и позволяя выполнить встроенное сравнение строк 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 );
} );

Ответ 2

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

Ответ 3

Я наткнулся на эту тему, ища такой же быстрый и грязный ответ, но он не касался того, что мне действительно нужно. "Как обрабатывать нули", плавать их сверху или снизу и т.д. Это то, что я придумал:

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

Ответ 4

Я пока не могу комментировать ответы, но я хотел поделиться своей проблемой, если кто-то еще использует решение Tims.

Решение Tims отлично работало. ОДНАКО... он периодически перебрасывал ошибку "Число ожидаемых". Полностью беспорядочно.

Эта ссылка объясняет проблему и обходной путь, который решил проблему для меня...

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

Надеюсь, это спасет кого-то, когда я потратил деньги на отладку/googling!

Ответ 5

Я еще не могу добавить комментарий к комментарию @robert, но здесь расширение на @robert, чтобы добавить поддержку для boolean:

[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, undefineds всегда загружаются в конец массива...

Ответ 6

Используйте настраиваемую функцию заказа, которая обрабатывает нулевые значения таким образом.

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

Ответ 7

Мое предложение по возрастанию сортировки массива со смешанными значениями (числа, строки, нули, неопределенные значения).

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

Ответ 8

Поскольку у меня остаются разные варианты использования для сортировки таких вещей, как 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;
}

Ответ 9

В браузере выполняется значение 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);

Ответ 10

Вы можете передать сортировку sortfunction

array.sort(sortfunction)

где sortfunction делает необходимое вам сравнение (регулярная сортировка с нулевыми значениями больше других)