2010-09-28 23 views
5

Mam szereg obiektów Javascript, które chciałbym współdziałać w kolejności zgodnej z rzeczywistością, która jest zawsze dodatnią liczbą całkowitą z opcjonalną pojedynczą literą na koniec. Szukam rozwiązanie, które działa w co najmniej Firefox 3 i Internet Explorer 8. najbliżej Doszedłem do takiej funkcji sortowania jest następująca:JavaScript w IE8: jak sortować tablicę obiektów według właściwości alfanumerycznych

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

Po tak sortowane, drukując arrayOfObjects daje :

1, bla, duże
1010, bla, małe
15, bla, małe
1A, bar, duży
1B, bar, mały
1C, bar, mały
1D Pasek, duże
1E, bar, duży
1F, bar, duży
1G, bla, małe
2, bla, małe
23, bla, małe
23C, bla, małe
3 foo , mały

jednak chciałbym arrayOfObjects wydrukować w kolejności poniżej:

1, foo, duży
1A, bar, duży
1B , Bar, mały
1C, bar, mały
1D, bar, duży
1E, bar, duży
1F, bar, duży
1G, bla, małe
2, bla, małe
3 bla, małe
15, bla, małe
23, bla, małe
23C, bla, małe
1010, bla, małe

Biorąc pod uwagę, w jaki sposób mogę rozwiązać ab ove funkcja, aby obiekty sortować według numeru jako klucz podstawowy i literę jako klucz dodatkowy? Z góry dziękuję za pomoc.

Odpowiedz

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

chodzi o podzielenie kluczy na części numeryczne i łańcuchowe.

edit (oops dostał "dopasowanie" zadzwonić do tyłu)

edycja ponownie @Ryan Tenney mądrze sugeruje, że anonimowa funkcja zewnętrzna nie jest to konieczne:

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

trochę prostsze.

+0

regex dosłowny nie dodawać żadnych kosztów dla każdej iteracji. Lepiej pozbyć się funkcji zewnętrznej samozachowawczej i zadeklarować splitter wewnątrz wewnętrznej funkcji. –

+0

Poza tym wspaniała odpowiedź. Jest on znacznie bardziej zwięzły niż odpowiedź, którą przygotowywałam do zaoferowania :) –

+0

Mam coś wspólnego z powtarzaniem wyrażeń regularnych - to nie tyle dla wydajności, ile dla utrzymania. Być może raz na sto prób, za pierwszym razem otrzymam wyrażenie regularne, więc chcę zminimalizować liczbę powtórzeń. Oczywiście mogłem po prostu wpisać to jako 'var' w ciele funkcji; Nie myślałem o tym zbyt wiele. – Pointy

0

Nie trzeba analizować liczbę całkowitą z ciągiem digits-

Jeśli oba ciągi cyfr meczu, wartość nie ma znaczenia, obejrzysz ewentualnego listu.

Jeśli cyfry się nie zgadzają, odjęcie jednej od drugiej wymusza liczby.

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

Tutaj jest porównanie funkcji, z nieco bardziej rozwlekły kodowych i sensownych nazw zmiennych:

/** 
* 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 
} 
Powiązane problemy