Ric*_*arn 70 python java iterator
在Python中,该enumerate函数允许您迭代一系列(索引,值)对.例如:
>>> numbers = ["zero", "one", "two"]
>>> for i, s in enumerate(numbers):
... print i, s
...
0 zero
1 one
2 two
Run Code Online (Sandbox Code Playgroud)
有没有办法在Java中这样做?
Ric*_*arn 54
对于实现该List接口的集合,您可以调用该listIterator()方法来获取ListIterator.迭代器(以及其他)有两种方法 - nextIndex()来获取索引; 并next()获取值(与其他迭代器一样).
所以上面的Python的Java等价物可能是:
List<String> numbers = Arrays.asList("zero", "one", "two");
ListIterator<String> it = numbers.listIterator();
while (it.hasNext()) {
System.out.println(it.nextIndex() + " " + it.next());
}
Run Code Online (Sandbox Code Playgroud)
像Python一样输出:
0 zero
1 one
2 two
Run Code Online (Sandbox Code Playgroud)
Pac*_*ace 14
我发现这与python方法最相似.
public static void main(String [] args) {
List<String> strings = Arrays.asList("zero", "one", "two");
for(EnumeratedItem<String> stringItem : ListUtils.enumerate(strings)) {
System.out.println(stringItem.index + " " + stringItem.item);
}
System.out.println();
for(EnumeratedItem<String> stringItem : ListUtils.enumerate(strings, 3)) {
System.out.println(stringItem.index + " " + stringItem.item);
}
}
Run Code Online (Sandbox Code Playgroud)
0 zero
1 one
2 two
3 zero
4 one
5 two
Run Code Online (Sandbox Code Playgroud)
import java.util.Iterator;
public class ListUtils {
public static class EnumeratedItem<T> {
public T item;
public int index;
private EnumeratedItem(T item, int index) {
this.item = item;
this.index = index;
}
}
private static class ListEnumerator<T> implements Iterable<EnumeratedItem<T>> {
private Iterable<T> target;
private int start;
public ListEnumerator(Iterable<T> target, int start) {
this.target = target;
this.start = start;
}
@Override
public Iterator<EnumeratedItem<T>> iterator() {
final Iterator<T> targetIterator = target.iterator();
return new Iterator<EnumeratedItem<T>>() {
int index = start;
@Override
public boolean hasNext() {
return targetIterator.hasNext();
}
@Override
public EnumeratedItem<T> next() {
EnumeratedItem<T> nextIndexedItem = new EnumeratedItem<T>(targetIterator.next(), index);
index++;
return nextIndexedItem;
}
};
}
}
public static <T> Iterable<EnumeratedItem<T>> enumerate(Iterable<T> iterable, int start) {
return new ListEnumerator<T>(iterable, start);
}
public static <T> Iterable<EnumeratedItem<T>> enumerate(Iterable<T> iterable) {
return enumerate(iterable, 0);
}
}
Run Code Online (Sandbox Code Playgroud)
严格地说,不,因为Python中的enumerate()函数返回元组列表,而Java中不存在元组.
但是,如果您感兴趣的是打印索引和值,那么您可以按照Richard Fearn的建议并在迭代器上使用nextIndex()和next().
还要注意,可以使用更通用的zip()函数(使用Python语法)定义enumerate():
mylist = list("abcd")
zip(range(len(mylist)), mylist)
Run Code Online (Sandbox Code Playgroud)
给[(0,'a'),(1,'b'),(2,'c'),(3,'d')]
如果您定义自己的Tuple类(请参阅在Java中使用Pairs或2-tuples作为起点),那么您当然可以轻松地在Java中编写自己的zip()函数来使用它(使用在中定义的Tuple类)链接):
public static <X,Y> List<Tuple<X,Y>> zip(List<X> list_a, List<Y> list_b) {
Iterator<X> xiter = list_a.iterator();
Iterator<Y> yiter = list_b.iterator();
List<Tuple<X,Y>> result = new LinkedList<Tuple<X,Y>>();
while (xiter.hasNext() && yiter.hasNext()) {
result.add(new Tuple<X,Y>(xiter.next(), yiter.next()));
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
一旦你有zip(),实现enumerate()是微不足道的.
编辑:工作缓慢的一天,所以完成它:
public static <X> List<Tuple<Integer,X>> enumerate (List<X> list_in) {
List<Integer> nums = new ArrayList<Integer>(list_in.size());
for (int x = 0; x < list_in.size(); x++) {
nums.add(Integer.valueOf(x));
}
return zip (nums, list_in);
}
Run Code Online (Sandbox Code Playgroud)
编辑2:正如对这个问题的评论所指出的,这并不完全等同.虽然它产生的值与Python的枚举值相同,但它并没有像Python的枚举那样以相同的生成方式实现.因此,对于大型馆藏,这种方法可能非常令人望而却步
根据 Python 文档(此处),这是您可以使用 Java 获得的最接近的结果,并且不再冗长:
String[] numbers = {"zero", "one", "two"}
for (int i = 0; i < numbers.length; i++) // Note that length is a property of an array, not a function (hence the lack of () )
System.out.println(i + " " + numbers[i]);
}
Run Code Online (Sandbox Code Playgroud)
如果您需要使用List该类...
List<String> numbers = Arrays.asList("zero", "one", "two");
for (int i = 0; i < numbers.size(); i++) {
System.out.println(i + " " + numbers.get(i));
}
Run Code Online (Sandbox Code Playgroud)
*注意:如果您需要在遍历列表时修改列表,则需要使用 Iterator 对象,因为它能够修改列表而不会引发ConcurrentModificationException.
简单明了
public static <T> void enumerate(Iterable<T> iterable, java.util.function.ObjIntConsumer<T> consumer) {
int i = 0;
for(T object : iterable) {
consumer.accept(object, i);
i++;
}
}
Run Code Online (Sandbox Code Playgroud)
示例用法:
void testEnumerate() {
List<String> strings = Arrays.asList("foo", "bar", "baz");
enumerate(strings, (str, i) -> {
System.out.println(String.format("Index:%d String:%s", i, str));
});
}
Run Code Online (Sandbox Code Playgroud)