Question

Pourquoi je ne peux pas utiliser table.sort pour trier les tables avec des index associatifs?

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top