массив сортировки javascript из смешанных строк и значений NULL - PullRequest
11 голосов
/ 24 февраля 2010

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

Спасибо!

Ответы [ 10 ]

13 голосов
/ 24 февраля 2010

Это будет делать то, что вы хотите, преобразовав все в строки (в частности, преобразовав ноль в пустую строку) и разрешив встроенное сравнение строк в 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 );
} );
7 голосов
/ 25 февраля 2010
[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);
});
4 голосов
/ 13 апреля 2012

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

    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 голосов
/ 16 июля 2015

Я пока не могу добавить комментарий к комментарию @ 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, неопределенные всегда загружаются до конца массива ...

3 голосов
/ 03 мая 2011

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

Решение Tims отлично сработало. ОДНАКО ... это бы периодически выдавало ошибку "Ожидаемое число". Совершенно случайно.

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

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

Надеюсь, это сэкономит кому-то время, потраченное на отладку и поиск в Google!

1 голос
/ 24 февраля 2010

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

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;
});
0 голосов
/ 19 декабря 2018

Поскольку у меня по-разному используются разные варианты сортировки, например, 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;
}
0 голосов
/ 13 ноября 2018

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

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', 'ААА', 'ааэ', 'жа', '  Жу', 'Эркер', 'Яромир Ягр'];
0 голосов
/ 24 февраля 2010

Вы можете передать функцию сортировки

array.sort(sortfunction)

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

0 голосов
/ 24 февраля 2010

Браузер выполняет 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...