Como obter o índice de um elemento ao percorrer um array em Swift? Entendendo uma questão popular
\n\nImagine: você está programando em Swift e quer não apenas percorrer um array, mas também saber em que posição cada elemento se encontra. Seja para modificar elementos pelo índice, comparar valores adjacentes ou simplesmente exibir uma lista numerada, a tarefa é a mesma. A pergunta "How to iterate a loop with index and element in Swift" acumulou milhares de visualizações no Stack Overflow. Isso significa que este tópico preocupa muitos.
\n\nNeste artigo, não vamos apenas dar uma resposta pronta. Vamos olhar por baixo dos panos: analisar quais métodos existem, qual é mais rápido, qual é mais seguro e por que um deles — enumerated() — se tornou o padrão de facto. Vamos lá!
O problema: por que o simples for-in não é suficiente?
\n\nSuponha que você tenha um array de strings:
\n\nlet fruits = ["Maçã", "Banana", "Cereja", "Melão"]\n\nA maneira mais óbvia é for-in:
for fruit in fruits {\n print(fruit)\n}\n\nIsso exibirá os nomes das frutas. Mas e se você precisar saber o índice? Por exemplo: "1. Maçã, 2. Banana..."? O simples for-in não fornece o índice. Você precisa criar gambiarras:
var index = 0\nfor fruit in fruits {\n print("\\(index). \\(fruit)")\n index += 1\n}\n\nFunciona? Sim. Bonito? Não. E se o array estiver vazio? E se você esquecer de incrementar o index? Bem-vindo ao mundo dos bugs. O Swift oferece soluções mais elegantes.
Método nº 1: O clássico — método enumerated()
\n\nEsta é a maneira mais popular e recomendada. O método enumerated() retorna uma sequência de tuplas (offset: Int, element: Element). Vejamos como funciona:
for (index, fruit) in fruits.enumerated() {\n print("\\(index + 1). \\(fruit)")\n}\n\nSaída:
\n1. Maçã\n2. Banana\n3. Cereja\n4. Melão\n\nO que acontece por baixo dos panos?
\n\nenumerated() não cria um novo array. Ele retorna uma sequência preguiçosa do tipo EnumeratedSequence. Isso significa que os elementos não são copiados para uma nova estrutura de dados — eles são "encapsulados" em tempo real. A cada acesso ao próximo elemento, a sequência simplesmente incrementa o contador e retorna uma tupla. Isso é muito eficiente em termos de memória, especialmente para coleções grandes.
Uma nuance importante: o offset sempre começa em 0. Se você precisar de um índice começando em 1 (como na numeração de listas), basta adicionar um. O Swift não faz isso por você — é uma decisão consciente dos desenvolvedores da linguagem para manter a consistência com a indexação de arrays.
enumerated() com forEach
\n\nO método forEach também suporta enumerated():
fruits.enumerated().forEach { (index, fruit) in\n print("\\(index). \\(fruit)")\n}\n\nA diferença entre for-in e forEach é importante: dentro de forEach não é possível usar break ou continue. Se precisar sair do loop prematuramente — use for-in.
Método nº 2: Indexação por intervalo (Range)
\n\nUma maneira antiga, mas ainda encontrada, é iterar pelos índices:
\n\nfor index in 0..<fruits.count {\n print("\\(index). \\(fruits[index])")\n}\n\nParece simples, mas existem armadilhas:
\n\n- \n
- Segurança: Se o array mudar durante a iteração (por exemplo, em código multithread),
fruits.countpode ficar desatualizado e você pode sair dos limites do array. \n - Legibilidade: O código parece mais "de baixo nível". Outros desenvolvedores gastarão um segundo extra para entender o que você está fazendo. \n
- Desempenho: O acesso por índice
fruits[index]é uma operação O(1) para arrays, mas para outras