Kann nicht mit assoziativer Indizes Tabelle sortieren
-
21-09-2019 - |
Frage
Warum kann ich nicht table.sort zu sortieren Tabellen mit assoziativen Indizes verwenden?
Lösung
Sie können nur sortieren Tabellen mit aufeinanderfolgenden ganzen Tasten beginnend bei 1, das heißt Listen. Wenn Sie eine andere Tabelle von Schlüssel-Wert-Paaren haben, können Sie eine Liste von Paaren zu machen und zu sortieren, dass:
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
Natürlich ist dies ist nur sinnvoll, wenn Sie eine benutzerdefinierte Bestellung liefern (lt
), die als Argument Schlüssel / Wert-Paare erwartet.
Dieses Problem wird noch ausführlicher in einer damit verbundenen Frage über das Sortieren diskutiert Lua Tabellen .
Andere Tipps
Generell Lua Tabellen sind reine assoziative Arrays. Es gibt kein „natürlichen“, um andere als die als Nebenwirkung von der jeweiligen Implementierung des Hash-Tabelle in Lua Kern verwendet. Dies macht Sinn, da die Werte von jedem Lua Datentyp (außer nil
) können sowohl als Schlüssel und Werte verwendet werden; aber nur Strings und Zahlen haben jede Art von sinnvoller Ordnung, und dann auch nur zwischen den Werten der gleichen Typ.
Zum Beispiel, was sollte die sortierten Reihenfolge dieser Tabelle sein:
unsortable = {
answer=42,
true="Beauty",
[function() return 17 end] = function() return 42 end,
[math.pi] = "pi",
[ {} ] = {},
12, 11, 10, 9, 8
}
Es hat eine String-Schlüssel, einen boolean Schlüssel, eine Funktionstaste, einen nicht-ganzzahligen Schlüssel, einen Tabellenschlüssel und fünf Integer-Schlüssel. Sollte die Funktion Art vor der Zeichenfolge? Wie beurteilen Sie die Zeichenfolge in eine Zahl vergleichen? Wo sollte die Tabelle sortieren? Und was ist userdata
und thread
Werte, die nicht passieren in dieser Tabelle angezeigt werden?
Nach Konvention durch aufeinanderfolgende ganze Zahlen indizierten Werte mit 1 beginnen, werden als Listen verwendet. Mehrere Funktionen und gemeinsame Idiome folgen dieser Konvention und table.sort
ist ein Beispiel. Funktionen, die Listen arbeiten über in der Regel alle Werte ignorieren auf Schlüssel gespeichert, die nicht Teil der Liste sind. Auch hier table.sort
ist ein Beispiel:. Es nur die Elemente sortiert, die an Schlüsseln gespeichert sind, der Teil der Liste ist
Ein weiteres Beispiel ist der #
Operator. Für die oben stehende Tabelle ist #unsortable
5 weil unsortable[5] ~= nil
und unsortable[6] == nil
. Beachten Sie, dass der Wert an der numerischen Index math.pi
gespeichert ist, nicht, obwohl pi gezählt ist zwischen 3 und 4, weil es nicht eine ganze Zahl ist. Weiterhin ist keine der anderen Nicht-ganzzahlige Schlüssel wird entweder gezählt. Dies bedeutet, dass eine einfache for-Schleife kann die gesamte Liste iterieren:
for i in 1,#unsortable do
print(i,unsortable[i])
end
Das ist zwar oft geschrieben als
for i,v in ipairs(unsortable) do
print(i,v)
end
Kurz gesagt, Lua Tabellen sind ungeordnete Sammlungen von Werten, die jeweils durch einen Schlüssel indiziert; aber es gibt eine spezielle Konvention für die sequentiellen ganzzahlige Schlüssel bei 1 beginnen.
Edit: Für den speziellen Fall von Nicht-Integral-Schlüssel mit einer geeigneten partiellen Ordnung, gibt es eine Behelfslösung einen separaten Indextabelle beinhaltet. Der beschriebene Inhalt von Tabellen, die von String-Werten verkeilt ist ein geeignetes Beispiel für diesen Trick.
Zuerst sammelt die Schlüssel in einer neuen Tabelle, in Form einer Liste. Das heißt, machen eine Tabelle von aufeinanderfolgenden ganzen Zahlen indiziert bei 1 mit Tasten als Werte beginnen und zu sortieren, dass. Dann verwendet diesen Index zu iterieren dem Originaltisch in der gewünschten Reihenfolge.
Zum Beispiel, hier ist foreachinorder()
, die diese Technik über alle Werte einer Tabelle Iterierte verwendet, eine Funktion für jeden Schlüssel / Wert-Paar, in einer durch eine Vergleichsfunktion bestimmt aufrufen.
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
Es erstellt einen Index, sortiert sie mit table.sort()
, dann Schleifen über jedes Element in dem sortierten Index und ruft die Funktion f
für jedes. Die Funktion f
ist der Schlüssel und Wert übergeben. Die Sortierreihenfolge wird durch eine optionale Vergleichsfunktion bestimmt, die an table.sort
geben wird. Es ist mit zwei Elementen vergleichen (die Schlüssel auf den Tisch t
in diesem Fall) genannt und muss true
zurück, wenn der erste kleiner als der zweite ist. Wenn nicht angegeben, verwendet table.sort
die eingebaute in <
Operator.
Zum Beispiel, angesichts der folgenden Tabelle:
t1 = {
a = 1,
b = 2,
c = 3,
}
dann foreachinorder(t1,print)
druckt:
a 1 b 2 c 3
und foreachinorder(t1,print,function(a,b) return a>b end)
druckt:
c 3 b 2 a 1
Weil sie keine Reihenfolge an erster Stelle. Es ist wie der Versuch, einen Müllsack voller Bananen zu sortieren.