Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over array twice (cartesian product) but consider only half the elements

I am trying to iterate over an array twice to have pairs of elements (e_i,e_j) but I only want the elements such that i < j.

Basically, what I want would look like this is C-like languages.

int my_array[N] = ...;
for (int i=0; i<N; i++)
        for (int j=i+1; j<N; j++)
                something(my_array[i],my_array[j]);

I didn't find what I was looking for in itertools (the closest thing I've found was itertools.product(*iterables[, repeat])).

I tried a few things but I am not really convinced by any of them :

my_list=range(10)

# Using enumerate and slices - explicit loop
res=[]
for i,j in enumerate(my_list):
        for k in my_list[i+1:]:
                res.append((j,k))
print res

# Using enumerate and slices - list comprehension
res=[(j,k) for i,j in enumerate(my_list) for k in my_list[i+1:]]
print res

# Using enumerate and xrange - explicit loop
res=[]
for i,j in enumerate(my_list):
        for k in range(i+1, len(my_list)):
                res.append((j,my_list[k]))
print res       

# Using enumerate and xrange - list comprehension
res=[(j,my_list[k]) for i,j in enumerate(my_list) for k in range(i+1, len(my_list))]
print res

I'm still convinced that there is a better and more pythonic solution. Any suggestion is welcome.

like image 711
SylvainD Avatar asked Sep 03 '25 15:09

SylvainD


2 Answers

Just use itertools.combinations(my_list, 2).

like image 119
BrenBarn Avatar answered Sep 05 '25 15:09

BrenBarn


Can't you just use the range function and go with:

vect = [...]
for i in range(0, len(vect)):
    for j in range(i+1, len(vect)):
        do_something()
like image 42
Paulo Bu Avatar answered Sep 05 '25 14:09

Paulo Bu