4

What is the equivalent of the following in python?

for (i=0; i<n; i++)
    for (j=i+1; j<n; j++)
        //do stuff with A[i], A[j]

Or in some sense, the following. It should also remove the element from A at the completion of each round of the loop.

for a in A:
    for a' in A/{a}: #i.e. rest of the elements of A
        #do something with a,a'
    #remove a from A

Is there a pythonic way of doing this without using enumerate()?

Edits:

Sorry for the bad description.

  1. In the first example, I mean to use i & j only as indices. Their values do not matter. Its just a rough c++ equivalent of the latter.

  2. The outer loop is executed n times. The inner loop is executed (n-1), (n-2)...0 times for each iteration of the outer loop.

Maybe this might help (pseudocode):

function next_iteration(list):
    head = first element
    tail = remaining elements #list
    each element in tail interacts with head one by one
    next_iteration(tail)

PS: All code samples above are pseudocodes. I'm trying to express something that is still a bit vague in my mind.

6
  • 2
    Your two loops don't do the same thing. Pick one! Commented Mar 20, 2012 at 13:31
  • 1
    @katrielalex -- not explicitly, but conceptually they could both represent nested loops over the same sequence, where the inner loop starts immediately after the current element in the outer loop. Commented Mar 20, 2012 at 13:41
  • The second example begins the inner loop at the start and only skips element a. Commented Mar 20, 2012 at 13:46
  • It need not be the 'next' element in the inner loop. The inner loop works on the 'remaining elements'. The next iteration is also on the remaining elements. Please see next_iteration to get a better idea. Commented Mar 20, 2012 at 14:16
  • Both katrielalex and hochl are correct I guess. I just have to use itertools.combinations instead of itertools.permutations. Is it possible to mark both as correct? Commented Mar 20, 2012 at 14:32

11 Answers 11

4

I intepret what you're asking as

How can I iterate over all pairs of distinct elements of a container?

Answer:

>>> x = {1,2,3}
>>> import itertools
>>> for a, b in itertools.permutations(x, 2):
...     print a, b
... 
1 2
1 3
2 1
2 3
3 1
3 2

EDIT: If you don't want both (a,b) and (b,a), just use itertools.combinations instead.

Sign up to request clarification or add additional context in comments.

2 Comments

All pairs of distinct elements, without considering the order of elements in each pair. how does this change to accomodate that?
@Karthick use .combinations instead. See the docs.
3

Since your two questions are different, here is solution for your second problem:

for i in xrange(len(A)):
    for j in xrange(len(A)):
        if i != j:
            do_stuff(A[i], A[j])

or using itertools (I think using the included batteries is very pythonic!):

import itertools

for a, b in itertools.permutations(A, 2):
    do_stuff(a, b)

This applies do_stuff to all combinations of 2 different elements from A. I you want to store the result just use:

[do_stuff(a, b) for a, b in itertools.permutations(A, 2)]

1 Comment

Hi, almost there. :) Can you make it work in such a way that (a,b) and (b,a) are the same? That is, order doesn't matter.
0

How about:

for i in range(0,n):
    for j in range (i+1,n):
    # do stuff

Comments

0
for i in range(0,n):
   for j in range(i+1,n):
   # do stuff

Comments

0

Still can't leave comments.. but basically what the other two posts said - but get in the habit of using xrange instead of range.

for i in xrange(0,n):
   for j in xrange(i+1,n):
   # do stuff

3 Comments

range() returns generator in python 3.x
It does, but the op never specified version so I tend to assume < 3.x :]
With 2.x on the way out and 3.x on the way in it is better to get in the habit of using range.
0

You could make the inner loop directly over a slice. Not saying this is any better, but it is another approach.

for i in range(0,len(x)):
  a = x[i]
  for b in x[i+1:]:
    print a, b

Comments

0

Another way to approach this is - if n is an sequence that provides the iterable interface, then in Python you can simplify your code by iterating over the object directly:

for i in n:
   for some_var in n[n.index(i):]: # rest of items
     # do something

I hope I understood your loop correctly, because as others have stated - they don't do the same thing.

Comments

0

For the first one of your questions, as already mentioned in other answers:

for i in xrange(n):
    for j in xrange(i+1, n):
        # do stuff with A[i] and A[j]

For the second one:

for i, a in enumerate(A):
    for b in A[i+1:]:
        # do stuff with a and b

Comments

0

Your psuedocode almost has it:

function next_iteration(list):
    head = first element
    tail = remaining elements #list
    each element in tail interacts with head one by one
    next_iteration(tail)

Python code:

def next_iteration(lst):
    head, tail = lst[0], lst[1:]
    for item in tail:
        print(head, item)
    if tail:
        next_iteration(tail)

Which, when tried with next_iteration([1, 2, 3]), prints:

1 2
1 3
2 3

Comments

0

You can use xrange to generate values for i and j respectively as show below:

for i in xrange(0, n):
   for j in xrange(i + 1, n):
       # do stuff

Comments

0

In the first for-loop, enumerate() walks through the array and makes the index,value of each element available to the second for-loop. In the second loop, range() makes j = i+1 --> len(a) available. At this point you'd have exactly what you need which is i & j to do your operation.

>>> a = [1,2,3,4]
>>> array_len = len(a)
>>> for i,v in enumerate(a):
...   for j in range(i+1, array_len):
...     print a[i], a[j]
...
1 2
1 3
1 4
2 3
2 4
3 4
>>>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.