是否有与Python的“枚举”函数等价的Java函数?

2024-05-04 11:53:45 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中,^{}函数允许您迭代(索引、值)对序列。例如:

>>> numbers = ["zero", "one", "two"]
>>> for i, s in enumerate(numbers):
...     print i, s
... 
0 zero
1 one
2 two

在Java中有什么方法可以做到这一点吗?


Tags: 方法函数infor序列javaoneprint
3条回答

我发现这与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);
    }
}

输出

0 zero
1 one
2 two

3 zero
4 one
5 two

特点

  • 在任何iterable上工作
  • 不创建内存中的列表副本(适用于大型列表)
  • 支持每种语法的本机
  • 接受可以添加到索引的start参数

实施

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

}

严格地说,不,因为Python中的enumerate()函数返回元组列表,而元组在Java中不存在。

但是,如果您感兴趣的只是打印索引和值,那么您可以按照Richard fern的建议在迭代器上使用nextIndex()和next()。

还要注意,枚举()可以使用更通用的zip()函数(使用Python语法)定义:

mylist = list("abcd")
zip(range(len(mylist)), mylist)

给出[(0,'a'),(1,'b'),(2,'c'),(3,'d')]

如果您定义了自己的元组类(请参见Using Pairs or 2-tuples in Java作为起点),那么您当然可以用Java编写自己的zip()函数来利用它(使用链接中定义的元组类):

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

一旦有了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);
}

编辑2:正如对这个问题的评论所指出的,这并不完全等同。虽然它生成的值与Python的enumerate相同,但它的生成方式与Python的enumerate不同。因此,对于大型收藏品来说,这种方法可能非常令人望而却步。

对于实现^{}接口的集合,可以调用^{}方法来获取^{}。迭代器(除其他外)有两个方法-^{},用于获取索引;和^{},用于获取值(与其他迭代器一样)。

因此,上述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());
}

它和Python一样,输出:

0 zero
1 one
2 two

相关问题 更多 >