2015-01-12 20 views
5

Tabloları alfabetik olarak sıralamak istiyorum. Numaralar hariç.Lua tabloları alfabetik olarak sırala, sayılar hariç

aşağıdaki kod tablosu karşılaştırıcı fonksiyonu ile nasıl sıralandığını gösterir:

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

Ama böyle sıralanabilir istiyorum::

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

beni verir

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

Mümkün mü?

+0

Sürücülerden tüm numaralar? Sadece ilk kelimeye göre mi sırala? vb. tablonuz büyükse ya da sık sık bunu yaptığınız "sort key" in bir önbelleğini saklamak muhtemelen iyi bir fikirdir. –

cevap

3

Bunu aslen gönderip yazacaktım, ancak lhf tarafından gönderilen çözüm, sorunuzu yanıtladı. Hala sorun yaşıyorsanız, aşağıdakileri deneyin.

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 

Baskılar: sıralamak önce anahtarından

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

Teşekkürler, bu daha iyi çalışır. Desen değiştirildi: ''(% D +) (% d +) $'' izin vermek için {N = 'Yeşil1'}, 'çalışmak gibi görünüyor ama bir şey gözden kaçmış olabilir. – Dreanh

+0

@Dreanh Bu desen iyi görünüyor ve renk adında hiçbir basamak olmadıkça çalışması gerekiyor, (. +) Herhangi bir karakter (ler) için çalışıyor. – Adam

+0

Tamam, teşekkürler. '^ (. +) (% D +) $' 'veya' '^ (% g) (% d +) $' 'kullanırsam işe yaramaz. – Dreanh

6

bu deneyin: "Yeşil 1" "Yeşil 02" ya da "Yeşil ile karşılaştırarak gibi, köşe davalarını gerekirse dikkate almak gerekebilir rağmen

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

Teşekkürler! İstediğim gibi çalıştı! – Dreanh

+0

Bir sorun var, tablodaki bazı dizelerin sayısından bahsetmedik. Yani bir hata alıyorum. – Dreanh

+0

Bu satırda hata oluştu: 'a1 [b1 veya (a1 == b1 ve a2 Dreanh

3

lhf çözümü, sizin için çalışması gerektiğini @ 2 "Yeşil" ile "2". Alphanum sıralamasını uygulamak için birkaç yöntemi inceledim ve sonuçlarını bir blog post ile karşılaştırdım. Bu konu hakkında discussion on the lua mail list numaralı telefonu da kontrol edebilirsiniz.