2010-01-19 2 views

Répondre

3

Vous ne pouvez trier les tables avec des clés entières consécutives à partir de 1, c'est-à-dire des listes. Si vous avez une autre table de paires clé-valeur, vous pouvez faire une liste de paires et trier que:

function sortpairs(t, lt) 
    local u = { } 
    for k, v in pairs(t) do table.insert(u, { key = k, value = v }) end 
    table.sort(u, lt) 
    return u 
end 

Bien sûr, cela est utile que si vous fournissez un ordre personnalisé (lt) qui prévoit que les principaux arguments/paires de valeurs.

Ce problème est traité plus en détail dans related question about sorting Lua tables.

+0

Donc vous dites tous les deux qu'il n'y a aucun moyen de trier une table avec des clés personnalisées (c'est-à-dire des chaînes de caractères) ??? J'ai vraiment aimé Lua, pour être un langage si flexible, mais même Java ou merdique (le meilleur lang. Jamais) C# peut le faire. – mnn

+1

Les tables Lua avec des clés à cordes sont * non * commandées. Si vous voulez commander un ensemble de paires clé-valeur, vous modifiez la représentation. –

+0

Mais je ne peux pas en obtenir un élément, car je dois enregistrer l'entier de l'entrée dans la table. Et cet index va changer après la suppression d'une entrée ... – mnn

2

Parce qu'ils n'ont aucun ordre en premier lieu. C'est comme essayer de trier un sac à ordures rempli de bananes.

+0

En fait, je pense que c'est plus comme essayer de trier un sac à dos plein de cœurs d'apple –

6

En général, les tables Lua sont des tableaux associatifs purs. Il n'y a pas d'ordre "naturel" autre que l'effet secondaire de l'implémentation particulière de la table de hachage utilisée dans le noyau de Lua. Cela est logique car les valeurs de tout type de données Lua (autre que nil) peuvent être utilisées à la fois comme des clés et des valeurs; mais seules les cordes et les nombres ont une sorte d'ordre sensible, et seulement entre des valeurs de même type.

Par exemple, que si l'ordre de tri de cette table soit:

unsortable = { 
    answer=42, 
    true="Beauty", 
    [function() return 17 end] = function() return 42 end, 
    [math.pi] = "pi", 
    [ {} ] = {}, 
    12, 11, 10, 9, 8 
} 

Il a une clé de chaîne, une clé booléenne, une touche de fonction, une touche non-intégrale, une clé de table, et cinq clés entières. La fonction devrait-elle trier en avant de la chaîne? Comment comparez-vous la chaîne à un nombre? Où devrait trier la table? Et qu'en est-il des valeurs userdata et thread qui n'apparaissent pas dans cette table? Par convention, les valeurs indexées par des entiers séquentiels commençant par 1 sont couramment utilisées en tant que listes. Plusieurs fonctions et idiomes communs suivent cette convention, et table.sort en est un exemple. Les fonctions qui opèrent sur des listes ignorent généralement les valeurs stockées sur les clés qui ne font pas partie de la liste. Encore une fois, table.sort est un exemple: il trie uniquement les éléments qui sont stockés sur les clés qui font partie de la liste. L'opérateur # est un autre exemple. Pour le tableau ci-dessus, #unsortable est 5 car unsortable[5] ~= nil et unsortable[6] == nil. Notez que la valeur stockée à l'index numérique math.pi n'est pas prise en compte même si pi est compris entre 3 et 4 car ce n'est pas un nombre entier. De plus, aucune des autres clés non entières n'est comptée non plus. Cela signifie qu'une simple boucle peut parcourir la liste complète:

for i in 1,#unsortable do 
    print(i,unsortable[i]) 
end 

Bien que ce soit souvent écrit

for i,v in ipairs(unsortable) do 
    print(i,v) 
end 

En bref, les tables Lua sont des collections non ordonnées de valeurs, indexées chacune par une clé ; mais il y a une convention spéciale pour les clés entières successives commençant à 1.

Edit: Pour le cas particulier des clés non solidaires d'un ordre partiel approprié, il y a un travail autour impliquant une table d'index séparé. Le contenu décrit des tables codées par des valeurs de chaîne est un exemple approprié pour cette astuce. Commencez par collecter les clés dans une nouvelle table, sous la forme d'une liste. C'est-à-dire, faites une table indexée par des entiers consécutifs commençant à 1 avec les clés comme valeurs et triez-la. Ensuite, utilisez cet index pour parcourir la table d'origine dans l'ordre souhaité.

Par exemple, voici foreachinorder(), qui utilise cette technique pour parcourir toutes les valeurs d'une table, en appelant une fonction pour chaque paire clé/valeur, dans un ordre déterminé par une fonction de comparaison.

function foreachinorder(t, f, cmp) 
    -- first extract a list of the keys from t 
    local keys = {} 
    for k,_ in pairs(t) do 
     keys[#keys+1] = k 
    end 
    -- sort the keys according to the function cmp. If cmp 
    -- is omitted, table.sort() defaults to the < operator 
    table.sort(keys,cmp) 
    -- finally, loop over the keys in sorted order, and operate 
    -- on elements of t 
    for _,k in ipairs(keys) do 
     f(k,t[k]) 
    end 
end 

Elle construit un index, il trie avec table.sort(), puis une boucle sur chaque élément de l'index trié et appelle la fonction f pour chacun d'eux. La fonction f reçoit la clé et la valeur. L'ordre de tri est déterminé par une fonction de comparaison optionnelle qui est transmise à table.sort. Il est appelé avec deux éléments à comparer (les clés de la table t dans ce cas) et doit renvoyer true si le premier est inférieur au second. S'il est omis, table.sort utilise l'opérateur < intégré.

Par exemple, étant donné le tableau suivant:

t1 = { 
    a = 1, 
    b = 2, 
    c = 3, 
} 

puis foreachinorder(t1,print) impressions:

 
a 1 
b 2 
c 3 

et foreachinorder(t1,print,function(a,b) return a>b end) impressions:

 
c 3 
b 2 
a 1 
+0

OK, comment puis-je trier alors? Après tout, je veux fournir ma propre fonction de comparaison, donc je ne sais pas pourquoi cela ne peut pas être fait. Tous les éléments de table ont le même modèle: key est une chaîne et value est une autre table. – mnn

+0

Voir mon edit pour un exemple en utilisant une deuxième table pour le tri. – RBerteig

Questions connexes