วิธีรับดัชนีลูปปัจจุบันเมื่อใช้ Iterator


108

ฉันใช้ Iterator เพื่อวนซ้ำผ่านคอลเลกชันและฉันต้องการรับดัชนีขององค์ประกอบปัจจุบัน

ฉันจะทำเช่นนั้นได้อย่างไร?



1
@finnw ฉันไม่คิดว่ามันจะซ้ำกัน คำถามนี้ถามโดยใช้ Iterator ส่วนอีกคำถามใช้สำหรับแต่ละลูป คำถามทั้งสองได้รับการแก้ไขโดยวิธีการที่คล้ายกันดังนั้นคำตอบจึงไม่ซ้ำกันของคำถาม
Robert

คำตอบ:


94

ใช้ตัวแปรของคุณเองและเพิ่มขึ้นในลูป


6
แต่ยังเห็น @ Mateusz-dymczyk it.nextIndex()เสนอแนะเกี่ยวกับ มีประโยชน์เมื่อคอลเลกชันเป็นรายการ
noamtm

114

ฉันมีคำถามเดียวกันและพบว่าการใช้ 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());
}

ตรวจสอบให้แน่ใจว่าคุณเรียก nextIndex ก่อนที่คุณจะได้รับ () ถัดไป


5
ขอบคุณที่พูดถึง 'Make sure you call the nextIndex before you get the next ()'
Gangadhar JANNU

ขอบคุณฉันไม่ทราบเรื่องนี้มาก่อน ข้อควรระวังที่ฉันควรทำคือ ListIterator เป็นแบบสองทิศทางในขณะที่ Iterator เป็นแบบทิศทางเดียว ตราบใดที่คุณหลีกเลี่ยงการเลื่อนไปมาพร้อมกับเคอร์เซอร์ที่มีประสิทธิภาพคุณก็ควรจะปลอดภัย
user2910265

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 # ถัดไปเพียงครั้งเดียวต่อลูป - ทำที่ด้านบนสุด)


3
หากคุณสร้างตัววนซ้ำด้วยตัวคุณเองคุณสามารถใช้ ListIterator ได้เช่นกันและไม่ต้องการตัวแปร int แยกต่างหาก
Robert Klemme

1
หากคุณใช้ 'การนำเข้าแบบคงที่' สำหรับ Arrays.asList คุณก็สามารถเขียนได้asList("zero", "one", "two")
karmakaze

นั่นเป็นวิธีที่ฉันทำก่อนที่จะอ่านคำตอบของพอล ฉันขอกีดกันทางของคุณเป็นอย่างยิ่งเพราะฉันไม่เห็นประโยชน์อะไรเลย คุณคิดว่ามีข้อได้เปรียบ (ยกเว้นข้อที่กล่าวถึง) ทำไมคุณไม่ใช้ for-each loop? การกำหนด Iterator อย่างชัดเจนไม่จำเป็นหากคุณใช้ตัวแปรของคุณเอง
Willi Mentzel

@progressive_overload หากคุณต้องการ Iterator (ตามคำถามเช่นเพื่อส่งไปยังไลบรารี) ซึ่งตัวอย่างจะไม่แสดง ในตัวอย่างนี้คุณมีตัวแปรนอกลูปและต้องระมัดระวังในการเรียก #next ครั้งเดียว ในตัวอย่างของ Paul ไม่มีตัวแปรนอกลูป แต่คุณต้องระมัดระวังในการเรียก #next และ #nextIndex พร้อมกัน (และในทางปฏิบัติหากใช้มากกว่าหนึ่งครั้งตัวแปรเหล่านั้นจะถูกดึงไปเป็นตัวแปรภายในซึ่งตัวอย่างนั้นไม่ได้ ' t แสดง)
Tom Clift

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

สะสมแบบไหน? หากเป็นการใช้งานอินเทอร์เฟซรายการคุณก็สามารถit.nextIndex() - 1ใช้ได้


4

ใช้ListIteratorเพื่อวนซ้ำผ่าน Collection หากคอลเล็กชันไม่ใช่รายการให้เริ่มใช้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 () จะต้องมีการสแกนรายการอุปกรณ์เพิ่มเติม การเพิ่มตัวนับในพื้นที่จะเร็วขึ้น
Greg Brown

1
ตกลง นี่ไม่ใช่วิธีแก้ปัญหาที่มีประสิทธิภาพสูงสุด
ซันนี่

1
ดูเหมือนว่าคุณอัปเดตตัวอย่างให้มีประสิทธิภาพมากขึ้น
Greg Brown

1

ดูที่นี่ .

iterator.nextIndex()next()จะให้ดัชนีขององค์ประกอบที่จะถูกส่งกลับโดยการเรียกภายหลัง


อินเตอร์เฟส Iterator ไม่มีเมธอด nextIndex () คุณจำเป็นต้องใช้ ListIterator อย่างชัดเจนสำหรับสิ่งนั้น แต่ OP ถามเกี่ยวกับ Iterator โดยเฉพาะ
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 ()
Henrik Aasted Sørensen

0

แม้ว่าคุณจะได้รับคำตอบแล้ว แต่ก็ควรเพิ่มข้อมูล

ดังที่คุณได้กล่าวถึงคอลเล็กชันอย่างชัดเจนคุณไม่สามารถใช้listIteratorเพื่อรับดัชนีสำหรับคอลเล็กชันทุกประเภท

รายการอินเทอร์เฟซ - ArrayList, LinkedList, Vector และ Stack

มีทั้งiterator()และlistIterator()

ตั้งค่าอินเทอร์เฟซ - HashSet, LinkedHashSet, TreeSet และ EnumSet

มีเพียง iterator()

อินเทอร์เฟซแผนที่ - HashMap, LinkedHashMap, TreeMap และ IdentityHashMap

ไม่เคยมีใคร iterators แต่สามารถใช้ซ้ำผ่าน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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.