Як отримати індекс поточного циклу при використанні Iterator?


107

Я використовую ітератор, щоб повторити колекцію і хочу отримати індекс поточного елемента.

Як я можу це зробити?



1
@finnw Я не думаю, що вони дублюють. Це питання задається за допомогою Iterator, інше - для кожного циклу. Обидва питання вирішуються аналогічним підходом, тому відповіді дублюються, а не питання.
Роберт

Відповіді:


92

Використовуйте власну змінну та збільшуйте її у циклі.


6
Але також див. Пропозицію @ mateusz-dymczyk про it.nextIndex(). Корисно, коли колекція - Список.
noamtm

113

У мене було те саме питання, і я виявив, що за допомогою ListIterator працював. Аналогічно тесту, наведеному вище:

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

ListIterator iter = list.listIterator();

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

Переконайтесь, що ви зателефонували до наступного ІНДЕКСУ ПЕРЕД, коли ви дійсно отримаєте наступний ().


5
Дякуємо, що згадали "Переконайтесь, що ви телефонуєте наступномуIndex, перш ніж ви дійсно отримаєте наступний ()"
Gangadhar JANNU

Спасибі, я про це раніше не знав. Я застережу, що ListIterator є двонаправленим, тоді як Iterator - однонаправленим. Поки ви уникаєте руху вперед-назад із тим, що фактично є курсором, тоді ви повинні бути в безпеці.
користувач2910265

28

Ось спосіб це зробити за допомогою власної змінної та зберігаючи її стисло:

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);
}

Вихід (ви здогадалися):

0: zero
1: one
2: two

Перевага полягає в тому, що ви не збільшуєте свій індекс в циклі (хоча вам потрібно бути обережним лише зателефонувати до Iterator # next один раз за цикл - просто зробіть це вгорі).


3
Якщо ви створюєте ітератор самостійно, ви також можете використовувати ListIterator, і не потрібна окрема змінна int.
Роберт Клемме

1
Якщо ви використовуєте "статичний імпорт" для Arrays.asList, ви можете просто написатиasList("zero", "one", "two")
karmakaze

саме так я це зробив і до того, як я прочитав відповідь Павла. Я б сильно відвернув ваш шлях, тому що я не бачу в цьому жодної переваги. Як ви вважаєте, чи є перевага (крім зазначеної). Чому ви не використовували цикл для кожного? Визначати Iterator чітко не потрібно, якщо ви використовуєте власну змінну.
Віллі Менцель

@progressive_overload, лише якщо вам потрібен ітератор (відповідно до запитання, наприклад, для передачі в бібліотеку), якого не показує приклад. У цьому прикладі у вас є змінна поза циклу, і вам потрібно бути обережним один раз викликати #next. У прикладі Павла немає змінних за межами циклу, але вам потрібно бути обережними один раз викликати #next і #nextIndex (і на практиці, якщо вони використовуються більше одного разу, вони будуть втягнуті в локальні змінні, що цей приклад не робить ' т показати).
Том Кліфт

23

Ви можете використовувати ListIteratorпідрахунок:

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

Яка колекція? Якщо це реалізація інтерфейсу List, то ви можете просто використовувати it.nextIndex() - 1.


4

Використовуйте ListIterator для перегляду колекції. Якщо колекція не є списком, який слід розпочати з використання, Arrays.asList(Collection.toArray())щоб спочатку перетворити його на список.


3

просто зробіть щось подібне:

        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
Для виклику indexOf () буде потрібно додаткове сканування списку пристроїв. Швидше буде просто наростити місцевий лічильник.
Грег Браун

1
домовились. це не найефективніше рішення.
Сонячно

1
Схоже, ви оновили приклад, щоб бути ефективнішим.
Грег Браун


1

Дивіться тут .

iterator.nextIndex()надав би індекс елемента, який буде повернутий при наступному виклику до next().


Ітератор інтерфейсу НЕ має метод nextIndex (). Для цього вам потрібно явно використовувати ListIterator, але ОП запитується спеціально про Ітератор.
Fran Marzoa

0

Все, що потрібно використовувати його iterator.nextIndex (), щоб повернути поточний індекс, на якому знаходиться ітератор. Це може бути трохи простіше, ніж використання власної змінної лічильника (яка все ще працює).

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); 
    }
}

Цей код буде проходити через list1, перераховуючи по одному предмету за раз та друкуючи текст елемента, потім "знаходиться в індексі", тоді він буде друкувати індекс, у якому його знайшов ітератор. :)


1
Насправді ваш код вимкнено одним, оскільки він намагається відобразити індекс ПІСЛЯ виклику його.next ().
Генрік Аастед Сьоренсен

0

Хоча ви вже мали відповідь, подумали додати трохи інформації.

Як ви прямо згадували про колекції, ви не можете використовувати listIteratorіндекс для всіх типів колекцій.

Інтерфейси списку - ArrayList, LinkedList, Vector та Stack.

Має і те, iterator()іlistIterator()

Встановити інтерфейси - HashSet, LinkedHashSet, TreeSet і EnumSet.

Має тільки iterator()

Інтерфейси карт - HashMap, LinkedHashMap, TreeMap та IdentityHashMap

Не має ітераторів, але їх можна повторити за допомогою keySet()/ values()або entrySet()як keySet()і entrySet()повертає Setта values()повертаєCollection .

Тому його краще використовувати iterators()з постійним збільшенням значення, щоб отримати поточний індекс для будь-якого типу колекції.


-1

Це було б найпростіше рішення!

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;

}

Випробуваний на gcc-9 з -std=c++11прапором

Вихід:

0
1
2
3
4

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.