For Loop em Lua

86

Minha tarefa é como fazer um loop for. Eu descobri isso em termos de números, mas não consigo descobrir em termos de nomes. Eu gostaria de criar um loop for que contenha uma lista de nomes. A seguir está o que eu tenho até agora:

names = {'John', 'Joe', 'Steve'}
for names = 1, 3 do
  print (names)
end

Tentei outras coisas, mas simplesmente não funciona, o terminal sempre lista apenas 1, 2, 3 ... O que estou fazendo de errado?

SamYoungNY
fonte

Respostas:

203

Seu problema é simples:

names = {'John', 'Joe', 'Steve'}
for names = 1, 3 do
  print (names)
end

Este código primeiro declara uma variável global chamada names. Então, você inicia um loop for. O laço for declara uma variável local que namestambém é chamada ; o fato de uma variável ter sido previamente definida com namesé totalmente irrelevante. Qualquer uso de namesdentro do loop for se referirá ao local , não ao global.

O loop for diz que a parte interna do loop será chamada com names = 1, then names = 2, e finalmente names = 3. O loop for declara um contador que conta do primeiro ao último número e chama o código interno uma vez para cada valor que conta.

O que você realmente queria era algo assim:

names = {'John', 'Joe', 'Steve'}
for nameCount = 1, 3 do
  print (names[nameCount])
end

A sintaxe [] é como você acessa os membros de uma tabela Lua. As tabelas Lua mapeiam "chaves" para "valores". Seu array cria automaticamente chaves do tipo inteiro, que aumentam. Portanto, a chave associada a "Joe" na tabela é 2 (os índices Lua sempre começam em 1).

Portanto, você precisa de um loop for que conta de 1 a 3, que você obtém. Você usa a variável de contagem para acessar o elemento da tabela.

No entanto, isso tem uma falha. O que acontece se você remover um dos elementos da lista?

names = {'John', 'Joe'}
for nameCount = 1, 3 do
  print (names[nameCount])
end

Agora, entendemos John Joe nil, porque tentar acessar valores de uma tabela que não existe resulta em nil. Para evitar isso, precisamos contar de 1 até o comprimento da mesa:

names = {'John', 'Joe'}
for nameCount = 1, #names do
  print (names[nameCount])
end

O #é o operador de comprimento. Funciona em tabelas e strings, retornando o comprimento de cada uma. Agora, não importa o quão grande ou pequeno namesseja, isso sempre funcionará.

No entanto, há uma maneira mais conveniente de iterar por meio de uma série de itens:

names = {'John', 'Joe', 'Steve'}
for i, name in ipairs(names) do
  print (name)
end

ipairsé uma função padrão da Lua que itera em uma lista. Este estilo de forloop, o iterator for loop, usa esse tipo de função iteradora. O ivalor é o índice da entrada na matriz. O namevalor é o valor desse índice. Basicamente, ele faz muito trabalho pesado para você.

Nicol Bolas
fonte
1
Então, for with ipairs () funciona como foreach () em outras línguas
boctulus
15
Ótima resposta, eu apenas acrescentaria que, no exemplo final, é bastante comum usar _quando o var não é usado. Exnames = {'John', 'Joe', 'Steve'} for _, name in ipairs(names) do print (name) end
Fraser de
19

Ao ler online ( tutorial de tabelas ), parece que as tabelas se comportam como arrays, então você está procurando:

Way1

names = {'John', 'Joe', 'Steve'}
for i = 1,3 do print( names[i] ) end

Way2

names = {'John', 'Joe', 'Steve'}
for k,v in pairs(names) do print(v) end

Way1 usa a tabela index/key, em sua tabela namescada elemento possui uma chave a partir de 1, por exemplo:

names = {'John', 'Joe', 'Steve'}
print( names[1] ) -- prints John

Então, basta ipassar de 1 para 3.

Em vez disso, no Way2 você especifica qual tabela deseja executar e atribui uma variável para sua chave e valor, por exemplo:

names = {'John', 'Joe', myKey="myValue" }
for k,v in pairs(names) do print(k,v) end

imprime o seguinte:

1   John
2   Joe
myKey   myValue
derp
fonte
6
Você leu o tutorial das tabelas, mas não viu ipairs? Ou a parte em pairsque não é necessário retornar os valores-chave em nenhuma ordem específica?
Nicol Bolas,
Na verdade, usei ipairsno início, mas quando adicionei o myKey="myValue"exemplo que precisa pairsda tecla não numérica, decidi alterar o resto pairstambém. Me desculpe se omiti que o pedido não é garantido com pares mas deixei o link ali para ele ler.
derp
1
names = {'John', 'Joe', 'Steve'}
for names = 1, 3 do
  print (names)
end
  1. Você está excluindo sua tabela e substituindo-a por um int
  2. Você não está tirando um valor da mesa

Tentar:

names = {'John','Joe','Steve'}
for i = 1,3 do
    print(names[i])
end
Elliot
fonte
1
Downvoter: forneça um motivo válido para downvoting. Mesmo que eu ache que a resposta é enganosa porque names(o contador de inteiros), conforme declarado no forescopo, introduz uma variável local, que obscurece names(a matriz da tabela) conforme declarado no escopo global.
Dejavu