сортировать массив объектов на основе строки + цифры c в JavaScript - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь отсортировать массив с помощью функции. Но когда число идет к двум, ди git сортировка не верна. В противном случае он показывает правильный результат. Пожалуйста, проверьте код.

это функция:

var arr = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a4", value: 1},{name: "a2", value: 1}];

var arr2 = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a14", value: 1},{name: "a12", value: 1}];

var sort = function (prop, arr) {  
    prop = prop.split('.');
    var len = prop.length;
    
    arr.sort(function (a, b) {
        var i = 0;
        while( i < len ) {
            a = a[prop[i]];
            b = b[prop[i]];
            i++;
        }
        if (a < b) {
            return -1;
        } else if (a > b) {
            return 1;
        } else {
            return 0;
        }
    });
    return arr;
};
arr = sort('name', arr);
arr2 = sort('name', arr2);
console.log(arr); // it's correct
console.log(arr2); // it's not correct

В этом случае я пытаюсь отсортировать массив по значению name.

Ответы [ 3 ]

3 голосов
/ 26 апреля 2020

Вы можете использовать цифру c сопоставление с String#localeCompare. Это позволит избежать лексикографии c сортировки и даст вам правильную цифру c порядок:

var a = "10";
var b = "2";

console.log( //false - string "10" does not come after "2" because 1 < 2
  "a > b:", 
   a > b
);
console.log( //-1 - `a` comes before `b`
  "a.localeCompare(b):", 
   a.localeCompare(b)
);
console.log( // 1 - `a` comes after `b`
  "a.localeCompare(b, undefined, {numeric: true}):",
   a.localeCompare(b, undefined, {numeric: true})
);

Обратите внимание, что это работает для строк . Если вы также хотите отсортировать числа, у вас есть два простых варианта:

  • Привести числа к строкам, а затем использовать сортировку строк с сортировкой чисел c. Он будет работать так же, и ваш код будет простым.
  • Используйте if, чтобы проверить, что вы сравниваете, и примените .localeCompare logi c для строк и другой логики c для чисел.

Оба сработают, но я лично предпочитаю первый, так как он не требует ведения разных дел. Таким образом, использование его в вашем решении дает правильные результаты:

var arr = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a4", value: 1},{name: "a2", value: 1}];

var arr2 = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a14", value: 1},{name: "a12", value: 1}];

var arr3 = [{name: "a", value: 3},{name: "a", value: 1},{name: "a", value: 14},{name: "a", value: 12}];

var sort = function (prop, arr) {  
    prop = prop.split('.');
    var len = prop.length;
    
    arr.sort(function (a, b) {var i = 0;
        while( i < len ) {
            a = a[prop[i]];
            b = b[prop[i]];
            i++;
        }
        
        //cast to string
        a = String(a);
        b = String(b);
        
        return a.localeCompare(b, undefined, {numeric: true})
    });
    return arr;
};
arr = sort('name', arr);
arr2 = sort('name', arr2);
console.log(arr); // it's correct
console.log(arr2); // it's correct

arr3 = sort('value', arr3);
console.log(arr3); // it's correct
1 голос
/ 26 апреля 2020

Вам нужно разделить буквы и цифры, а затем сравнить их

var arr = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a4", value: 1},{name: "a2", value: 1}];

var arr2 = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a14", value: 1},{name: "a12", value: 1}];

var arr3 = [{name: 1, value: 1},{name: 11, value: 1},{name: 14, value: 1},{name: 12, value: 1}];
var sort = function (prop, arr) {  
    prop = prop.split('.');
    var len = prop.length;
    
    arr.sort(function (a, b) {
        var i = 0;
        while( i < len ) {
            a = a[prop[i]];
            b = b[prop[i]];
            i++;
        }
        let [key1,digit1] = (""+a).split(/(?<=[a-z])(?=\d)/)
        let [key2,digit2] = (""+b).split(/(?<=[a-z])(?=\d)/)
        return (key1 - key2) || (+digit1 - +digit2)
    });
    return arr;
};
arr = sort('name', arr);
arr2 = sort('name', arr2);
arr3 = sort('name', arr3)
console.log(arr); // it's correct
console.log(arr2); // it's not correct
console.log(arr3);
0 голосов
/ 26 апреля 2020

Свойство Name имеет тип string, поэтому сортировка выполняется в лексикографическом порядке (ie в алфавитном порядке). Вам нужно будет разобрать имя поля, чтобы отсортировать по номеру внутри имени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...