Как отсортировать множество чисел как лексикографически, так и численно?

В настоящее время у меня есть набор строк, которые являются просто числами и числами с + или -. Такие как:

1, 1+, 1-, 2, 2+, 2-, 10

Который, когда я сортирую, используя функции сортировки JavaScript, выдает:

1, 1+, 1-, 10, 2, 2+, 2-

это лексикографически, но не численно. Есть ли способ отсортировать это так, чтобы числа выходили правильным образом (первый список)? Я использую хранилища ExtJS, поэтому предпочтение отдается ответам в качестве сортировщика, но простой javascript тоже подойдет. Спасибо?

Изменить: это не просто сортировка чисел.

6 ответов

Решение

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

var numbers = ['1', '1-', '1+', '2', '2+', '2-', '10'];

numbers.sort(function (a, b){
    var _a = parseFloat(a), // If the values are integers only, parseInt will do too
        _b = parseFloat(b);
    if (_a - _b === 0) {
     return (a > b) ? 1 : -1;
    } else {
     return _a - _b;
    }
});

console.log(numbers);

Функция проверяет, равны ли числовые значения, и если да, возвращается к лексикографическому порядку для сортировки суффиксов символов. Если в одинаковом регистре нет суффиксов, следовательно, независимо от того, в каком порядке возвращаются числа. Если только один из операндов имеет суффикс, пустое число возвращает отрицательное значение. Если числовые значения не равны, функция просто возвращает тристат, т.е. a - b, который будет оцениваться по одному из negative, 0, positive, Или на самом деле это "бистат", так как мы обработали 0 дело уже.


Более общее решение

Приведенный выше код является частным случаем только для двух разных односимвольных суффиксов. Если суффиксы являются более сложными, вот более общий код для сортировки по номеру и суффиксу:

var numbers = ['1', '1-r', '1+q', '1', '2', '2+q', '2-r', '10'];
function suffixSort (suff, asc) {
    asc = 2 * +(!!asc) - 1; // Convert boolean to -1 or 1
    return function (a, b) {
        var _a = parseFloat(a), // Extract the number value
            _b = parseFloat(b),
            aSI = -(a.length - _a.toString().length), // Get the index of suffix start
            bSI = -(b.length - _b.toString().length);
        // Equal number values, sort by suffixes
        if (_a === _b) {
            return (suff.indexOf(a.substr(aSI)) > suff.indexOf(b.substr(bSI))) ? 1 : -1;
        }
        // Inequal number values, sort by numbers
        return asc * (_a - _b);
    }
}
// suffixSort arguments
//   suff: An array of the suffix strings to sort, ordered in the desired sorting order
//   asc:  true = ascending, false = descending. Optional, defaults to descending sort
numbers.sort(suffixSort(['+q', '-r'], true));
console.log(numbers);

Идея состоит в том, чтобы сохранить суффиксы в массиве, и когда необходима сортировка суффиксов, функция сравнивает индексы массивов суффиксов вместо самих суффиксов.

suffixSort Позволяет вам также выбрать направление сортировки. Выбранное направление сортировки не влияет на сортировку суффиксов, они всегда возвращаются в порядке их появления suff массив.

Вы могли бы использовать Array#sortи разделите элементы на числа и остальные, затем верните разницу или разницу в порядке.

var array = ['10', '2', '2+', '2-', '1', '1+', '1-'];

array.sort(function (a, b) {
    var r = /\d+|\D+/g,
        aa = a.match(r),
        bb = b.match(r),
        order = { '+': 1, '-': 2 };

    return aa[0] - bb[0] || (order[aa[1]] || 0) - (order[bb[1]] || 0);
});

console.log(array);

Эти значения являются почти целыми числами, поэтому сравнивая их по praseInt почти доставит вас туда. Единственное, чего не хватает, так это специального обращения со значениями, которые имеют одинаковую целочисленную x- должен прийти первым, потом x и наконец x+:

function specialChar(s) {
    c = s.substr(-1);
    if (c == '+') {
        return 1;
    }
    if (c == '-') {
      return -1;
    }
    return 0;
}

function numCompare(a, b) {
    aNum = parseInt(a);
    bNum = parseInt(b);
    cmp = aNum - bNum;
    if (cmp != 0) {
        return cmp;
    }
    // Integer parts are equal - compare the special char at the end
    return specialChar(a) - specialChar(b);
}

arr = ['1' , '1+', '1-', '2', '2+', '2-', '10'];
arr.sort(numCompare);

Если существует только три возможных состояния числа, и состояния имеют порядок number, number+, number Состояния могут быть воссозданы путем создания представления чисел в массиве, удаления уникальных чисел из массива, от минимума до максимума, конкатенации пустой цифры или арифметического оператора в требуемом порядке к номеру, а затем передачи значения в массив, где .toString() может использоваться для просмотра разделенного запятыми строкового представления отсортированных значений в массиве

var str = `314+, 1-, 7+, 1, 1-, 271-, 10-
          , 10+, 271, 271+, 314-, 314
          , 10, 2-, 2, 2+, 7-, 7`;

for (var [nums, order, res, num] = [str.match(/\d+/g), ["", "+", "-"], [], null]
     ; nums.length
     ; num = Math.min.apply(Math, nums)
       , res = [...res, ...order.map(op => num + op)]
       , nums = nums.filter(n => n != num)
    );

console.log(res.toString() + "\n", res);

  var result=[]; 
        result=array.map(function(n){
          if(typeof n==='number') return n;
            if(n[n.length-1]=='+'){
              return parseInt(n.substring(0,n.length-1))
              }
            else if(n[n.length-1]=='-'){
               return 0-parseInt(n.substring(0,n.length-1))
               }
            });
 result.sort(function(a,b){return a-b})

Предполагая, что вы просто хотите выбросить символы, вы можете использовать parseInt и Array#sort, чтобы получить порядок численно.

var data = ['1' , '1+', '1-', '2', '2+', '2-', '10'];
var sortedData = data.sort(function(a,b){return parseInt(a)-parseInt(b);});
Другие вопросы по тегам