Ne peut pas trier le tableau avec des indices associatifs
-
21-09-2019 - |
Question
Pourquoi je ne peux pas utiliser table.sort pour trier les tables avec des index associatifs?
La solution
Vous ne pouvez trier les tables avec des clés entières consécutives à partir de 1, à savoir, 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 attend comme arguments paires clé / valeur.
Cette question est abordée plus longuement dans une question relative sur le tri tables Lua .
Autres conseils
En général, les tables Lua sont des tableaux associatifs purs. Il n'y a pas d'effet « naturel » autre ordre que l'un de côté de la mise en œuvre de la table de hachage particulier utilisé dans le noyau Lua. Cela est logique parce que les valeurs de tout type de données Lua (autres que nil
) peuvent être utilisés comme les clés et les valeurs; mais seulement les chaînes et les nombres ont tout type de commande sensible, et seulement entre les valeurs de type similaire.
Par exemple, ce qui devrait l'ordre de tri de ce tableau est:
unsortable = {
answer=42,
true="Beauty",
[function() return 17 end] = function() return 42 end,
[math.pi] = "pi",
[ {} ] = {},
12, 11, 10, 9, 8
}
Il possède une clé de chaîne, une clé booléenne, une touche de fonction, une touche non intégrale, une clé de table, et cinq touches de nombres entiers. Si la fonction de tri avant de la chaîne? Comment comparez-vous la chaîne à un numéro? Où doit trier le tableau? Qu'en est-il des valeurs de userdata
et thread
qui ne se produisent pas apparaître dans ce tableau?
Par convention, les valeurs indexées par des entiers séquentiels commençant par 1 sont couramment utilisés sous forme de listes. Plusieurs fonctions et idiomes suivent cette convention et table.sort
est un exemple. Les fonctions qui opèrent sur les listes ignorent généralement toutes les valeurs stockées à des clés qui ne font pas partie de la liste. Encore une fois, table.sort
est un exemple. Trie uniquement les éléments qui sont stockés à des clés qui font partie de la liste
Un autre exemple est l'opérateur #
. Pour le tableau ci-dessus, #unsortable
est 5 parce unsortable[5] ~= nil
et unsortable[6] == nil
. Notez que la valeur stockée à l'index numérique math.pi
n'est pas compté, même si pi est compris entre 3 et 4 parce qu'il est pas un entier. En outre, aucune des autres touches non entières sont comptées soit. Cela signifie qu'une simple boucle peut itérer sur toute la liste:
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 sont Lua collections non ordonnées de valeurs, indexées chacune par une clé; mais il y a une convention particulière pour les touches de nombres entiers séquentiels commençant à 1.
Modifier 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 par des valeurs de calée chaîne est un exemple approprié pour cette astuce.
D'abord, récupérer les clés dans une nouvelle table, sous la forme d'une liste. Autrement dit, faire un tableau indexé par des nombres entiers consécutifs commençant à 1 avec les touches comme des valeurs et de tri que. Ensuite, utilisez cet index pour itérer sur la table d'origine dans l'ordre souhaité.
Par exemple, voici foreachinorder()
, qui utilise cette technique pour itérer sur toutes les valeurs d'une table, appeler 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és et appelle la fonction f
pour chacun d'eux. La fonction f
est passée la clé et la valeur. L'ordre de tri est déterminé par une fonction de comparaison en option qui est passé à table.sort
. Elle est appelée avec deux éléments à comparer (les clés de la table t
dans ce cas) et doit revenir true
si la première est inférieure à la seconde. En cas d'omission, table.sort
utilise l'opérateur <
intégré.
Par exemple, étant donné le tableau suivant:
t1 = {
a = 1,
b = 2,
c = 3,
}
puis imprime foreachinorder(t1,print)
:
a 1 b 2 c 3
et imprime foreachinorder(t1,print,function(a,b) return a>b end)
:
c 3 b 2 a 1
Parce qu'ils n'ont pas pour en premier lieu. Il est comme essayer de trier un sac poubelle plein de bananes.