2015-01-12 15 views
5

Chciałbym posortować tabelę alfabetycznie. Z wyjątkiem liczb.Lua sortuj tabelę alfabetycznie, z wyjątkiem liczb:

Poniższy kod pokazuje jak tablica jest posortowana z funkcji komparatora:

function(a,b) return a.N < b.N end 

daje mi:

obj = { 
    [1] = { 
     ["N"] = "Green 1"; 
    }; 
    [2] = { 
     ["N"] = "Green 11"; 
    }; 
    [3] = { 
     ["N"] = "Green 2"; 
    }; 
    [4] = { 
     ["N"] = "Red 1"; 
    }; 
} 

Ale ma to być klasyfikowane tak:

obj = { 
    [1] = { 
     ["N"] = "Green 1"; 
    }; 
    [2] = { 
     ["N"] = "Green 2"; 
    }; 
    [3] = { 
     ["N"] = "Green 11"; 
    }; 
    [4] = { 
     ["N"] = "Red 1"; 
    }; 
} 

Czy to możliwe?

+0

usunąć wszystkie numery z kluczem przed sortowania? Sortować tylko na pierwszym słowie? itp. Jeśli Twój stół jest duży lub będziesz to robił często utrzymywanie pamięci podręcznej "klucza sortowania", który generujesz, jest również dobrym pomysłem. –

Odpowiedz

3

Zamierzasz opublikować to pierwotnie, ale rozwiązanie opublikowane przez Lhf odpowiedziało na twoje pytanie. Ponieważ nadal występują problemy, spróbuj poniższych rozwiązań.

local function cmp(a, b) 
    a = tostring(a.N) 
    b = tostring(b.N) 
    local patt = '^(.-)%s*(%d+)$' 
    local _,_, col1, num1 = a:find(patt) 
    local _,_, col2, num2 = b:find(patt) 
    if (col1 and col2) and col1 == col2 then 
     return tonumber(num1) < tonumber(num2) 
    end 
    return a < b 
end 

local obj = { 
    { N = '1'   }, 
    { N = 'Green1'  }, -- works with optional space 
    { N = 'Green'  }, -- works when doesn't fit the format 
    { N = 'Sky blue99' }, 
    { N = 'Green 11' }, 
    { N = 'Green 2'  }, 
    { N = 'Red 02'  }, -- works when has leading zeros 
    { N = 'Red 01' }, -- works with padding spaces 
    { N = 'Sky blue 42' }, -- works with multi-word color names 
    { N = 99   }, -- works with numbers 
} 

table.sort(obj, cmp) 
for i,v in ipairs(obj) do 
    print(i, v.N) 
end 

Wydruki:

1 1 
2 99 
3 Green 
4 Green1 
5 Green 2 
6 Green 11 
7 Red 01 
8 Red 02 
9 Sky blue 42 
10 Sky blue99 
+0

Dzięki, to działa lepiej. Zmieniono wzorzec na: ''^ (% D +) (% d +) $'', aby zezwolić na '{N = 'Green1'}},' wydaje się działać, ale mogło coś przeoczyć. – Dreanh

+0

@Dreanh Ten wzór wygląda dobrze i powinien działać tak długo, jak długo nie ma żadnych cyfr w nazwie koloru, (. +) Działa dla dowolnego znaku (znaków). – Adam

+0

Ok, dzięki. Jeśli użyję ''^ (. +) (% D +) $'' lub ''^ (% g) (% d +) $" 'to nie działa. – Dreanh

6

Spróbuj tego:

local function split(a) 
    local x,y=a.N:match("(%S+)%s+(%S+)") 
    return x,tonumber(y) 
end 

table.sort(obj, 
    function (a,b) 
     local a1,a2=split(a) 
     local b1,b2=split(b) 
     return a1<b1 or (a1==b1 and a2<b2) 
    end 
) 
+0

Dzięki! To działało tak, jak tego chciałem! – Dreanh

+0

Masz jednak problem, nie wspomniałem, że niektóre ciągi w tabeli nie mają numeru. Więc dostaję błąd. – Dreanh

+0

Błąd w tej linii: 'return a1 Dreanh

3

@ rozwiązanie LHF powinien pracować dla Ciebie, choć być może trzeba rozważyć, czy trzeba obsłużyć przypadków narożne, jak porównywanie „Zielona 1” z „Zielona 02” lub „Zielony 2 "z" Zielonym 02 ". Dokonałem przeglądu kilku metod implementacji sortowania alfanumerycznego i porównałem ich wyniki w postaci blog post. Możesz również sprawdzić discussion on the lua mail list na ten temat.

Powiązane problemy