Cum să iterați prin tabel în Lua? (Programare, Array-Uri, Bucle, Lua, Cheie, Tabel Lua)

Lămâie de lămâie a intrebat.

Deci, am un tabel ceva de genul acesta:

arr =
{
  apples = { 'a', "red", 5 },
  oranges = { 'o', "orange", 12 },
  pears = { 'p', "green", 7 }
}

Nu se pare că este posibil să le accesez pe baza indexului lor, iar valorile în sine sunt tabele, așa că am făcut doar prima valoare a tabelului imbricate indexul acestuia, așa că acum arată așa:

arr =
{
  apples = { 0, 'a', "red", 5 },
  oranges = { 1, 'o', "orange", 12 },
  pears = { 2, 'p', "green", 7 }
}

Astfel, acum, de fiecare dată când folosesc unul dintre aceste tabele, știu care este indicele, dar tot nu pot ajunge la tabel folosind indicele, așa că am început să scriu o funcție care să le parcurgă pe toate și să verifice indicii până când îl găsește pe cel corect. Apoi mi-am dat seama… cum pot să le parcurg în buclă dacă nu pot deja să mă refer la ele prin indexul lor? Deci, acum sunt blocat. Chiar vreau să pot tasta arr.mere vs arr[1] în majoritatea timpului, dar, desigur, este necesar să le fac pe amândouă uneori.

Comentarii

  • Acest lucru cu răspunsul de la @greatwolf va eșua dacă nu există un „,” între fiecare rând de matrice. arr = { apples = { 0, 'a', "red", 5 }, oranges = { 1, 'o', "orange", 12 }, pears = { 2, 'p', "green", 7 }, } un exemplu funcțional poate fi văzut la: ideone.com/yWKHx7 –  > Por Kjell Hedström.
  • @KjellHedström Am editat întrebarea OP-ului și am corectat erorile minore de sintaxă. bună observație. –  > Por greatwolf.
4 răspunsuri
greatwolf

Pentru a itera peste toate perechile cheie-valoare dintr-un tabel, puteți utiliza pairs:

for k, v in pairs(arr) do
  print(k, v[1], v[2], v[3])
end

ieșiri:

pears   2   p   green
apples  0   a   red
oranges 1   o   orange

Editează: Rețineți că Lua nu garantează nicio ordine de iterație pentru partea asociativă a tabelului. Dacă doriți să accesați elementele într-o anumită ordine, preluați cheile de la arr și sortați-le. Apoi accesați arr prin intermediul cheilor sortate:

local ordered_keys = {}

for k in pairs(arr) do
    table.insert(ordered_keys, k)
end

table.sort(ordered_keys)
for i = 1, #ordered_keys do
    local k, v = ordered_keys[i], arr[ ordered_keys[i] ]
    print(k, v[1], v[2], v[3])
end

ieșiri:

  apples  a   red     5
  oranges o   orange  12
  pears   p   green   7

Comentarii

  • Tocmai am observat… de ce le tipărește în ordine greșită? Dacă le tipărește în ordine, aș putea renunța la variabila index în tabel și m-aș putea baza doar pe ordinea în care se tipărește pentru a găsi indexul, ceea ce ar fi bine. –  > Por Lemony Lime.
  • Lua nu garantează ordinea de iterație pentru partea asociativă a tabelului. –  > Por greatwolf.
  • @Lemony Am adăugat un exemplu despre cum poți parcurge tabelul într-o anumită ordine. –  > Por greatwolf.
  • @HenrikErlandsson – Un obiect JSON nu este ordonat. A se vedea spec. –  > Por beatgammit.
  • Când Crockford scrie „Un obiect este un set neordonat de perechi nume/valoare”, el vrea să spună că un șir JSON reprezintă un obiect cu perechi a căror ordine nu trebuie să se bazeze. Cu toate acestea, JSON este un format de schimb de text, iar ceea ce oamenii numesc „obiect JSON” este de fapt doar un șir de caractere, deci da, perechile sunt ordonate. Personal, cred că termenul „obiect JSON” este folosit în exces. Henrik are dreptate când spune că ideea ca cineva să dorească să itereze în ordinea dată în șirul JSON este una validă, dar „greșită”, într-adevăr! –  > Por Ray Toal.
frr171

Dacă doriți să vă referiți la un tabel imbricate prin mai multe chei, puteți să le atribuiți chei separate. Tabelele nu sunt duplicate și fac în continuare referire la aceleași valori.

arr = {}
apples = {'a', "red", 5 }
arr.apples = apples
arr[1] = apples

Acest bloc de cod vă permite să parcurgeți toate perechile cheie-valoare dintr-un tabel (http://lua-users.org/wiki/TablesTutorial):

for k,v in pairs(t) do
 print(k,v)
end

Baggef

Pentru cei care se întreabă de ce ipairs nu tipărește tot timpul toate valorile din tabel, iată de ce (aș comenta acest lucru, dar nu am suficiente puncte de băiat bun).

Funcția ipairs funcționează numai pe tabelele care au un element cu cheia 1. Dacă există un element cu cheia 1, ipairs va încerca să meargă cât de departe poate într-o ordine secvențială, 1 -> 2 -> 3 -> 4 etc., până când nu găsește un element cu o cheie care să fie următoarea în secvență. Ordinea elementelor nu contează.

Tabelele care nu îndeplinesc aceste cerințe nu vor funcționa cu ipairs, utilizați pairs în schimb.

Exemple:

ipairsCompatable = {"AAA", "BBB", "CCC"}
ipairsCompatable2 = {[1] = "DDD", [2] = "EEE", [3] = "FFF"}
ipairsCompatable3 = {[3] = "work", [2] = "does", [1] = "this"}

notIpairsCompatable = {[2] = "this", [3] = "does", [4] = "not"}
notIpairsCompatable2 = {[2] = "this", [5] = "doesn't", [24] = "either"}

ipairs va merge cât de departe poate cu iterațiile sale, dar nu va itera peste niciun alt element din tabel.

kindofIpairsCompatable = {[2] = 2, ["cool"] = "bro", [1] = 1, [3] = 3, [5] = 5 }

La imprimarea acestor tabele, acestea sunt ieșirile. De asemenea, am inclus pairs pentru comparație.

ipairs + ipairsCompatable
1       AAA
2       BBB
3       CCC

ipairs + ipairsCompatable2
1       DDD
2       EEE
3       FFF

ipairs + ipairsCompatable3
1       this
2       does
3       work

ipairs + notIpairsCompatable

pairs + notIpairsCompatable
2       this
3       does
4       not

ipairs + notIpairsCompatable2

pairs + notIpairsCompatable2
2       this
5       doesnt
24      either

ipairs + kindofIpairsCompatable
1       1
2       2
3       3

pairs + kindofIpairsCompatable
1       1
2       2
3       3
5       5
cool    bro

sgowd

Toate răspunsurile de aici sugerează să folosiți ipairs, dar aveți grijă, nu funcționează tot timpul.

t = {[2] = 44, [4]=77, [6]=88}

--This for loop prints the table
for key,value in next,t,nil do 
  print(key,value) 
end

--This one does not print the table
for key,value in ipairs(t) do 
  print(key,value) 
end

Comentarii

  • De ce nu se imprimă tot timpul? –  > Por Zeruno.
  • Sunt începător la Lua. Nu știu. Dar am întâlnit această problemă în timp ce îmi testam codul. –  > Por sgowd.
  • @sgowd de ce adaugi „,nil” după tabelul „t” – nu este necesar. De asemenea, problema menționată de tine (de fapt, nu este o problemă) este că ipairs returnează un set de chei bazate pe numere întregi. Asta înseamnă că, dacă tabelul dvs. are chei bazate pe șiruri de caractere, folosind ipairs le convertiți în chei întregi. Documentația descrie foarte clar diferența. –  > Por Seniru Pasan.
  • @SeniruPasan Mulțumesc pentru sfatul de a nu adăuga ‘,nil’; voi încerca. În exemplul pe care l-am dat, cheile sunt chei bazate pe numere întregi. Răspunsul lui Baggef stackoverflow.com/a/60088452/1566608 oferă mai multă claritate cu privire la motivul pentru care ipairs nu funcționează tot timpul. –  > Por sgowd.