Làm thế nào để lấy chỉ mục vòng lặp hiện tại khi sử dụng Iterator?


107

Tôi đang sử dụng một Iterator để lặp qua một tập hợp và tôi muốn lấy chỉ mục của phần tử hiện tại.

Làm thế nào tôi có thể làm điều đó?



1
@finnw Tôi không nghĩ rằng chúng trùng lặp. Câu hỏi này được hỏi bằng cách sử dụng Iterator, câu hỏi kia đang sử dụng vòng lặp for-each. Cả hai câu hỏi đều được giải theo cách tiếp cận tương tự, vì vậy các câu trả lời trùng lặp không phải là câu hỏi.
Robert

Câu trả lời:


92

Sử dụng biến của riêng bạn và tăng nó trong vòng lặp.


6
Nhưng cũng có thể xem đề xuất @ mateusz-dymczyk về it.nextIndex(). Hữu ích khi bộ sưu tập là một Danh sách.
noamtm

113

Tôi đã có cùng một câu hỏi và thấy rằng việc sử dụng ListIterator đã hoạt động. Tương tự như thử nghiệm ở trên:

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

ListIterator iter = list.listIterator();

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

Đảm bảo rằng bạn gọi nextIndex TRƯỚC KHI bạn thực sự nhận được nextIndex ().


5
Cảm ơn bạn đã đề cập đến 'Hãy chắc chắn rằng bạn gọi chỉ số tiếp theo TRƯỚC KHI bạn thực sự nhận được chỉ số tiếp theo ()'
Gangadhar JANNU 22/12/16

Cảm ơn, tôi đã không biết về điều này trước đây. Thận trọng mà tôi sẽ thực hiện là ListIterator là hai chiều trong khi Iterator là một chiều. Miễn là bạn tránh di chuyển qua lại với những gì thực sự là con trỏ, thì bạn sẽ được an toàn.
user2910265

28

Đây là một cách để làm điều đó bằng cách sử dụng biến của riêng bạn và giữ cho nó ngắn gọn:

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

Đầu ra (bạn đoán nó):

0: zero
1: one
2: two

Ưu điểm là bạn không tăng chỉ mục của mình trong vòng lặp (mặc dù bạn cần phải cẩn thận chỉ gọi tiếp theo Iterator # một lần cho mỗi vòng lặp - chỉ cần thực hiện ở trên cùng).


3
Nếu bạn tự tạo trình lặp, bạn cũng có thể sử dụng ListIterator và không cần biến int riêng biệt.
Robert Klemme,

1
Nếu bạn sử dụng một 'import static' cho Arrays.asList sau đó bạn chỉ có thể viếtasList("zero", "one", "two")
karmakaze

đó chính xác là cách tôi đã làm trước khi tôi đọc câu trả lời của Paul. Tôi thực sự không khuyến khích cách làm của bạn, bởi vì tôi không thấy có lợi gì cho nó. Bạn có nghĩ rằng có một lợi thế (ngoại trừ một trong những đề cập). Tại sao bạn không sử dụng vòng lặp for-each? Việc xác định lặp lại một cách rõ ràng là không cần thiết, nếu bạn sử dụng biến của riêng mình.
Willi Mentzel

@progressive_overload chỉ khi bạn cần một Iterator (theo câu hỏi, ví dụ: để chuyển tới thư viện), ví dụ này không hiển thị. Trong ví dụ này, bạn có một biến bên ngoài vòng lặp và cần phải cẩn thận gọi #next một lần. Trong ví dụ của Paul không có biến nào bên ngoài vòng lặp, nhưng bạn cần phải cẩn thận khi gọi #next và #nextIndex cùng nhau một lần (và trong thực tế, nếu được sử dụng nhiều lần, chúng sẽ được kéo vào các biến cục bộ, mà ví dụ đó không ' t hiện).
Tom Clift

23

Bạn có thể sử dụng ListIteratorđể đếm:

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

Bộ sưu tập kiểu gì? Nếu đó là một triển khai của giao diện Danh sách thì bạn chỉ có thể sử dụng it.nextIndex() - 1.


4

Sử dụng ListIterator để lặp qua Bộ sưu tập. Nếu Bộ sưu tập không phải là Danh sách để bắt đầu sử dụng Arrays.asList(Collection.toArray())để biến nó thành Danh sách trước.


3

chỉ cần làm một cái gì đó như thế này:

        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
Gọi indexOf () sẽ yêu cầu quét thêm danh sách thiết bị. Sẽ nhanh hơn nếu chỉ cần tăng một bộ đếm cục bộ.
Greg Brown

1
đã đồng ý. đây không phải là giải pháp hiệu quả nhất.
Sunny

1
Có vẻ như bạn đã cập nhật ví dụ để hiệu quả hơn.
Greg Brown,


1

Xem tại đây .

iterator.nextIndex()sẽ cung cấp chỉ mục của phần tử sẽ được trả về bằng lệnh gọi tới next().


Giao diện Iterator KHÔNG có phương thức nextIndex (). Bạn cần sử dụng ListIterator một cách rõ ràng cho việc đó, nhưng OP đã hỏi cụ thể về Iterator.
Fran Marzoa

0

Tất cả những gì bạn cần để sử dụng nó là iterator.nextIndex () để trả về chỉ mục hiện tại của trình vòng lặp. Điều này có thể dễ dàng hơn một chút so với việc sử dụng biến bộ đếm của riêng bạn (biến bộ đếm vẫn hoạt động).

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

Mã này sẽ đi qua danh sách list1 từng mục một và in văn bản của mục đó, sau đó "đang ở chỉ mục" sau đó nó sẽ in chỉ mục mà trình lặp tìm thấy nó ở đó. :)


1
Trên thực tế, mã của bạn bị tắt từng cái một vì nó cố gắng hiển thị chỉ mục SAU KHI gọi nó.next ().
Henrik Aasted Sørensen,

0

Mặc dù bạn đã có câu trả lời, hãy nghĩ rằng hãy thêm một số thông tin.

Như bạn đã đề cập đến Bộ sưu tập một cách rõ ràng, bạn không thể sử dụng listIteratorđể lấy chỉ mục cho tất cả các loại bộ sưu tập.

Liệt kê các giao diện - ArrayList, LinkedList, Vector và Stack.

Có cả hai iterator()listIterator()

Đặt giao diện - HashSet, LinkedHashSet, TreeSet và EnumSet.

Chỉ có iterator()

Giao diện bản đồ - HashMap, LinkedHashMap, TreeMap và IdentityHashMap

Không có trình vòng lặp, nhưng có thể được lặp lại bằng cách sử dụng thông qua keySet()/ values()hoặc entrySet()as keySet()entrySet()trả về Setvalues()trả vềCollection .

Vì vậy, tốt hơn là sử dụng iterators()với sự gia tăng liên tục của một giá trị để có được chỉ mục hiện tại cho bất kỳ loại tập hợp nào.


-1

Đây sẽ là giải pháp đơn giản nhất!

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;

}

Đã thử nghiệm trên gcc-9 với -std=c++11 cờ

Đầu ra:

0
1
2
3
4

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.