Como obter o índice do loop atual ao usar o Iterator?


107

Estou usando um Iterador para iterar por meio de uma coleção e desejo obter o índice do elemento atual.

Como eu posso fazer isso?



1
@finnw Não acho que sejam duplicados. Esta pergunta é feita usando o Iterator, a outra está usando o loop for-each. Ambas as questões são resolvidas por uma abordagem semelhante, portanto, as respostas são duplicadas e não a questão.
Robert

Respostas:


92

Use sua própria variável e a incremente no loop.


6
Mas veja também a sugestão de @matusz-dymczyk sobre it.nextIndex(). Útil quando a coleção é uma Lista.
noamtm

113

Eu tive a mesma dúvida e descobri que usar um ListIterator funcionou. Semelhante ao teste acima:

List<String> list = Arrays.asList("zero", "one", "two");

ListIterator iter = list.listIterator();

while (iter.hasNext()) {
    System.out.println("index: " + iter.nextIndex() + " value: " + iter.next());
}

Certifique-se de chamar o nextIndex ANTES de realmente obter o next ().


5
Obrigado por mencionar 'Certifique-se de ligar para o nextIndex ANTES de realmente obter o próximo ()'
Gangadhar JANNU

Obrigado, eu não sabia disso antes. O cuidado que eu faria é que ListIterator é bidirecional, enquanto Iterator é unidirecional. Contanto que você evite mover-se para frente e para trás com o que é efetivamente um cursor, você estará seguro.
user2910265

28

Esta é uma maneira de fazer isso usando sua própria variável e mantendo-a concisa:

List<String> list = Arrays.asList("zero", "one", "two");

int i = 0;
for (Iterator<String> it = list.iterator(); it.hasNext(); i++) {
    String s = it.next();
    System.out.println(i + ": " + s);
}

Resultado (você adivinhou):

0: zero
1: one
2: two

A vantagem é que você não incrementa seu índice dentro do loop (embora você precise ter cuidado para chamar Iterator # next apenas uma vez por loop - apenas faça isso no topo).


3
Se você mesmo criar o iterador, poderá usar um ListIterator também e não precisará da variável int separada.
Robert Klemme de

1
Se você usar uma 'importação estática' para Arrays.asList, pode simplesmente escreverasList("zero", "one", "two")
karmakaze

foi exatamente assim que fiz antes de ler a resposta de Paulo. Eu desencorajaria fortemente o seu caminho, porque não vejo nenhuma vantagem nisso. Você acha que há uma vantagem (exceto para o mencionado). Por que você não usou um loop for-each? Definir o Iterator explicitamente não é necessário, se você usar sua própria variável.
Willi Mentzel

@progressive_overload apenas se você precisar de um Iterador (conforme a pergunta, por exemplo, para passar para a biblioteca), que o exemplo não mostra. Neste exemplo, você tem uma variável fora do loop e precisa ter o cuidado de chamar #next uma vez. No exemplo de Paul, não há variáveis ​​fora do loop, mas você precisa ter cuidado para chamar #next e #nextIndex juntos uma vez (e na prática, se usados ​​mais de uma vez, eles seriam puxados para variáveis ​​locais, o que aquele exemplo não faz t mostrar).
Tom Clift

23

Você pode usar ListIteratorpara fazer a contagem:

final List<String> list = Arrays.asList("zero", "one", "two", "three");

for (final ListIterator<String> it = list.listIterator(); it.hasNext();) {
    final String s = it.next();
    System.out.println(it.previousIndex() + ": " + s);
}

12

Que tipo de coleção? Se for uma implementação da interface List, você pode simplesmente usar it.nextIndex() - 1.


4

Use um ListIterator para iterar pela coleção. Se a coleção não for uma lista para começar, use primeiro Arrays.asList(Collection.toArray())para transformá-la em uma lista.


3

apenas faça algo assim:

        ListIterator<String> it = list1.listIterator();
        int index = -1;
        while (it.hasNext()) {
            index++;
            String value = it.next();
            //At this point the index can be checked for the current element.

        }

4
Chamar indexOf () exigirá uma verificação adicional da lista de dispositivos. Será mais rápido simplesmente incrementar um contador local.
Greg Brown,

1
acordado. esta não é a solução mais eficiente.
Ensolarado de

1
Parece que você atualizou o exemplo para ser mais eficiente.
Greg Brown


1

Veja aqui .

iterator.nextIndex()forneceria o índice do elemento que seria retornado pela chamada subsequente para next().


A interface Iterator NÃO possui o método nextIndex (). Você precisa usar explicitamente um ListIterator para isso, mas o OP questionou especificamente sobre o Iterator.
Fran Marzoa de

0

Tudo o que você precisa é usar iterator.nextIndex () para retornar o índice atual em que o iterador está. Isso pode ser um pouco mais fácil do que usar sua própria variável de contador (que ainda funciona também).

public static void main(String[] args) {    
    String[] str1 = {"list item 1", "list item 2", "list item 3", "list item 4"};
    List<String> list1 = new ArrayList<String>(Arrays.asList(str1));

    ListIterator<String> it = list1.listIterator();

    int x = 0;

    //The iterator.nextIndex() will return the index for you.
    while(it.hasNext()){
        int i = it.nextIndex();
        System.out.println(it.next() + " is at index" + i); 
    }
}

Este código irá percorrer a lista list1 um item de cada vez e imprimir o texto do item, então "está no índice" então ele irá imprimir o índice em que o iterador o encontrou. :)


1
Na verdade, seu código está errado porque ele tenta exibir o índice DEPOIS de chamá-lo.next ().
Henrik Aasted Sørensen

0

Embora você já tenha a resposta, pensei em adicionar algumas informações.

Como você mencionou Coleções explicitamente, você não pode usar listIteratorpara obter o índice para todos os tipos de coleções.

Interfaces de lista - ArrayList, LinkedList, Vector e Stack.

Tem ambos iterator()elistIterator()

Definir interfaces - HashSet, LinkedHashSet, TreeSet e EnumSet.

Tem apenas iterator()

Interfaces de mapa - HashMap, LinkedHashMap, TreeMap e IdentityHashMap

Não tem iteradores, mas pode ser iterado usando keySet()/ values()ou entrySet()como keySet()e entrySet()retorna Sete values()retornaCollection .

Portanto, é melhor usar iterators()com incremento contínuo de um valor para obter o índice atual para qualquer tipo de coleção.


-1

Essa seria a solução mais simples!

std::vector<double> v (5);

for(auto itr = v.begin();itr != v.end();++itr){

 auto current_loop_index = itr - v.begin();

  std::cout << current_loop_index << std::endl;

}

Testado em gcc-9 com -std=c++11 flag

Resultado:

0
1
2
3
4

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.