Javascript в IE8: как отсортировать массив объектов по буквенно-цифровому свойству - PullRequest
5 голосов
/ 29 сентября 2010

У меня есть массив Javascript-объектов, которые я бы хотел совместимо сортировать по свойству, которое всегда является положительным целым числом с необязательной одиночной буквой в конце.Я ищу решение, которое работает по крайней мере в Firefox 3 и Internet Explorer 8. Наиболее близкой к такой функции сортировки является следующее:

var arrayOfObjects = [{id: '1A', name: 'bar', size: 'big'}, {id: '1C', name: 'bar', size: 'small'}, {id: '1', name: 'foo', size: 'big'}, {id: '1F', name: 'bar', size: 'big'}, {id: '1E', name: 'bar', size: 'big'}, {id: '1B', name: 'bar', size: 'small'}, {id: '1D', name: 'bar', size: 'big'}, {id: '1G', name: 'foo', size: 'small'},  {id: '3', name: 'foo', size: 'small'}, {id: '23', name: 'foo', size: 'small'}, {id: '2', name: 'foo', size: 'small'}, {id: '1010', name: 'foo', size: 'small'}, {id: '23C', name: 'foo', size: 'small'}, {id: '15', name: 'foo', size: 'small'}]

arrayOfObjects.sort(function(a, b){
    return (a.id < b.id ? -1 : a.id == b.id ? 0 : 1);
});

После такой сортировки распечаткаarrayOfObjects дает:

1, foo, big
1010, foo, small
15, foo, small
1A, bar, big
1B, bar, small
1C, бар, маленький
1D, бар, большой
1E, бар, большой
1F, бар, большой
1G, foo, маленький
2, foo, маленький
23, foosmall
23C, foo, small
3, foo, small

Однако я бы хотел, чтобы arrayOfObjects печатал в следующем порядке:

1, foo, big
1A, бар, большой
1B, бар, маленький
1C, бар, маленький
1D, бар, большой
1E, бар, большой
1F, бар, большой
1G, foo, маленький
2, foo, маленький
3, foo, маленький
15, foo, маленький
23, foo, маленький
23C, foo, маленький
1010,foo, small

Учитывая это, как я могу исправить вышеуказанную функцию, чтобы объекты сортировались по номеру в качестве первичного ключаа письмо как вторичный ключ?Заранее спасибо за любую помощь.

Ответы [ 3 ]

3 голосов
/ 29 сентября 2010
arrayOfObjects.sort((function() {
  var splitter = /^(\d+)([A-Z]*)/;
  return function(a, b) {
    a = a.id.match(splitter); b = b.id.match(splitter);
    var anum = parseInt(a[1], 10), bnum = parseInt(b[1], 10);
    if (anum === bnum)
      return a[2] < b[2] ? -1 : a[2] > b[2] ? 1 : 0;
    return anum - bnum;
  }
})());

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

edit (упс получил вызов "match" в обратном направлении)

отредактируйте снова @Ryan Tenney мудро предполагает, что анонимная внешняя функция на самом деле не нужна:

arrayOfObjects.sort(function(a, b) {
  var splitter = /^(\d+)([A-Z]*)/;
  a = a.id.match(splitter); b = b.id.match(splitter);
  var anum = parseInt(a[1], 10), bnum = parseInt(b[1], 10);
  if (anum === bnum)
    return a[2] < b[2] ? -1 : a[2] > b[2] ? 1 : 0;
  return anum - bnum;     
});

немного проще.

0 голосов
/ 24 сентября 2014

Вот функция сравнения с немного более подробным кодом и значимыми именами переменных:

/**
* Sort array ba numerical & alphabetical order ["1a", "2z", "2a", 99, 100]
*/
function compare(a, b) { 

    var re = /(\d+)([^ ]?)/, numA, numB, charA, charB,
        aMatches = re.exec(a),
        bMatches = re.exec(b) ;

    numA = aMatches[1] ? aMatches[1] : ''; //get the number part
    charA = aMatches[2] ? aMatches[2] : ''; //get the char part

    numB = bMatches[1] ? bMatches[1] : '';
    charB = bMatches[2] ? bMatches[2] : '';

    if (charA || charB){ //if one or both of the compare candidates have letter
        if (numA==numB){ //only if number parts are equal
            return charA.localeCompare(charB); // we compare letters 
        }
    }

    return numA - numB; // otherwise just compare numbers
}
0 голосов
/ 29 сентября 2010

Вам не нужно анализировать целое число из строки цифр -

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

Если цифры не совпадают, вычитание одной из другой приводит к приведению чисел.

var rx=/^(\d+)(\D?)$/;

    arrayOfObjects.sort(function(a, b){ 
        var id_a= a.id.match(rx), id_b= b.id.match(rx);
        if(id_a[1]== id_b[1]){
            if(id_a[2]=== id_b[2]) return 0;
            else{
                if(!id_a[2]) return -1;
                if(!id_b[2]) return 1;
                return id_a[2]> id_b[2]? 1: -1;
            }
        }
        return id_a[1]-id_b[1];
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...