Is there a Java equivalent of Python's 'enumerate' function?

前端 未结 11 566
别那么骄傲
别那么骄傲 2020-12-08 01:59

In Python, the enumerate function allows you to iterate over a sequence of (index, value) pairs. For example:

>>> numbers = [\"zero\", \"one\", \"tw         


        
相关标签:
11条回答
  • 2020-12-08 02:04

    No. Maybe there are some libraries for supporting such a functionality. But if you resort to the standard libraries it is your job to count.

    0 讨论(0)
  • 2020-12-08 02:06

    I think this should be the java functionality that resemble the python "enumerate" most, though it is quite complicated and inefficent. Basically, just map the list's indices to its elements, using ListIterator or Collector:

    List<String> list = new LinkedList<>(Arrays.asList("one", "two", "three", "four"));
    Map<Integer, String> enumeration = new Map<>();
    ListIterator iter = list.listIterator();
    while(iter.hasNext){
        map.put(iter.nextIndex(), iter.next());
    }
    

    or using lambda expression:

    Set<Integer, String> enumeration = IntStream.range(0, list.size()).boxed.collect(Collectors.toMap(index -> index, index -> list.get(index)));
    

    then you can use it with an enhanced for loop:

    for (Map.Entry<Integer, String> entry : enumeration.entrySet){
        System.out.println(entry.getKey() + "\t" + entry.getValue());
    }
    
    0 讨论(0)
  • 2020-12-08 02:07

    Simple and straightforward

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

    Sample usage:

    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));
        });
    }
    
    0 讨论(0)
  • 2020-12-08 02:11

    Strictly speaking, no, as the enumerate() function in Python returns a list of tuples, and tuples do not exist in Java.

    If however, all you're interested in is printing out an index and a value, then you can follow the suggestion from Richard Fearn & use nextIndex() and next() on an iterator.

    Note as well that enumerate() can be defined using the more general zip() function (using Python syntax):

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

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

    If you define your own Tuple class (see Using Pairs or 2-tuples in Java as a starting point), then you could certainly easily write your own zip() function in Java to make use of it (using the Tuple class defined in the link):

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

    And once you have zip(), implementing enumerate() is trivial.

    Edit: slow day at work, so to finish it off:

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

    Edit 2: as pointed out in the comments to this question, this is not entirely equivalent. While it produces the same values as Python's enumerate, it doesn't do so in the same generative fashion that Python's enumerate does. Thus for large collections this approach could be quite prohibitive.

    0 讨论(0)
  • 2020-12-08 02:13

    By combining generics with anonymous interfaces, you can essentially create a factory method for handing enumeration. The Enumerator callback hides the messiness of the iterator underneath.

    import java.util.Arrays;
    import java.util.List;
    import java.util.ListIterator;
    
    public class ListUtils2 {
        public static interface Enumerator<T> {
            void execute(int index, T value);
        };
    
        public static final <T> void enumerate(final List<T> list,
                final Enumerator<T> enumerator) {
            for (ListIterator<T> it = list.listIterator(); it.hasNext();) {
                enumerator.execute(it.nextIndex(), it.next());
            }
        }
    
        public static final void enumerate(final String[] arr,
                final Enumerator<String> enumerator) {
            enumerate(Arrays.asList(arr), enumerator);
        }
    
        public static void main(String[] args) {
            String[] names = { "John", "Paul", "George", "Ringo" };
    
            enumerate(names, new Enumerator<String>() {
                @Override
                public void execute(int index, String value) {
                    System.out.printf("[%d] %s%n", index, value);
                }
            });
        }
    }
    

    Result

    [0] John
    [1] Paul
    [2] George
    [3] Ringo
    

    Extended Thoughts

    Map, Reduce, Filter

    I have taken this a step further and created map, reduce, and filter functions based on this concept.

    Both Google's Guava and Apache common-collections dependencies include similar functionality. You can check them out as you wish.

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.ListIterator;
    
    public class ListUtils {
        // =========================================================================
        // Enumerate
        // =========================================================================
        public static abstract interface Enumerator<T> {
            void execute(int index, T value, List<T> list);
        };
    
        public static final <T> void enumerate(final List<T> list,
                final Enumerator<T> enumerator) {
            for (ListIterator<T> it = list.listIterator(); it.hasNext();) {
                enumerator.execute(it.nextIndex(), it.next(), list);
            }
        }
    
        // =========================================================================
        // Map
        // =========================================================================
        public static interface Transformer<T, U> {
            U execute(int index, T value, List<T> list);
        };
    
        public static final <T, U> List<U> transform(final List<T> list,
                final Transformer<T, U> transformer) {
            List<U> result = new ArrayList<U>();
            for (ListIterator<T> it = list.listIterator(); it.hasNext();) {
                result.add(transformer.execute(it.nextIndex(), it.next(), list));
            }
            return result;
        }
    
        // =========================================================================
        // Reduce
        // =========================================================================
        public static interface Reducer<T, U> {
            U execute(int index, T value, U result, List<T> list);
        };
    
        public static final <T, U> U reduce(final List<T> list,
                final Reducer<T, U> enumerator, U result) {
            for (ListIterator<T> it = list.listIterator(); it.hasNext();) {
                result = enumerator.execute(it.nextIndex(), it.next(), result, list);
            }
            return result;
        }
    
        // =========================================================================
        // Filter
        // =========================================================================
        public static interface Predicate<T> {
            boolean execute(int index, T value, List<T> list);
        };
    
        public static final <T> List<T> filter(final List<T> list,
                final Predicate<T> predicate) {
            List<T> result = new ArrayList<T>();
            for (ListIterator<T> it = list.listIterator(); it.hasNext();) {
                int index = it.nextIndex();
                T value = it.next();
                if (predicate.execute(index, value, list)) {
                    result.add(value);
                }
            }
            return result;
        }
    
        // =========================================================================
        // Predefined Methods
        // =========================================================================
        // Enumerate
        public static <T> String printTuples(List<T> list) {
            StringBuffer buff = new StringBuffer();
    
            enumerate(list, new Enumerator<T>() {
                @Override
                public void execute(int index, T value, List<T> list) {
                    buff.append('(').append(index).append(", ")
                        .append(value).append(')');
                    if (index < list.size() - 1) {
                        buff.append(", ");
                    }
                }
            });
    
            return buff.toString();
        }
    
        // Map
        public static List<String> intToHex(List<Integer> list) {
            return transform(list, new Transformer<Integer, String>() {
                @Override
                public String execute(int index, Integer value, List<Integer> list) {
                    return String.format("0x%02X", value);
                }
            });
        }
    
        // Reduce
        public static Integer sum(List<Integer> list) {
            return reduce(list, new Reducer<Integer, Integer>() {
                @Override
                public Integer execute(int index, Integer value, Integer result,
                        List<Integer> list) {
                    return result + value;
                }
            }, 0);
        }
    
        // Filter
        public static List<Integer> evenNumbers(List<Integer> list) {
            return filter(list, new Predicate<Integer>() {
                @Override
                public boolean execute(int index, Integer value, List<Integer> list) {
                    return value % 2 == 0;
                }
            });
        }
    
        // =========================================================================
        // Driver
        // =========================================================================
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(8, 6, 7, 5, 3, 0, 9);
    
            // Enumerate
            System.out.printf("%-10s: %s%n", "Enumerate", printTuples(numbers));
    
            // Map
            System.out.printf("%-10s: %s%n", "Map", intToHex(numbers));
    
            // Reduce
            System.out.printf("%-10s: %d%n", "Reduce", sum(numbers));
    
            // Filter
            System.out.printf("%-10s: %s%n", "Filter", evenNumbers(numbers));
        }
    }
    
    0 讨论(0)
  • 2020-12-08 02:14

    For collections that implement the List interface, you can call the listIterator() method to get a ListIterator. The iterator has (amongst others) two methods - nextIndex(), to get the index; and next(), to get the value (like other iterators).

    So a Java equivalent of the Python above might be:

    List<String> numbers = Arrays.asList("zero", "one", "two");
    ListIterator<String> it = numbers.listIterator();
    while (it.hasNext()) {
        System.out.println(it.nextIndex() + " " + it.next());
    }
    

    which, like the Python, outputs:

    0 zero
    1 one
    2 two
    
    0 讨论(0)
提交回复
热议问题