10

Suppose I have a list:

l = [0, 1, 2, 3]

How can I iterate over the list, taking each item along with its complement from the list? That is,

for item, others in ...
    print(item, others)

would print

0 [1, 2, 3]
1 [0, 2, 3]
2 [0, 1, 3]
3 [0, 1, 2]

Ideally I'm looking for a concise expression that I can use in a comprehension.

ecatmur
  • 152,476
  • 27
  • 293
  • 366

3 Answers3

13

This is quite easy and understandable:

for index, item in enumerate(l):
    others = l[:index] + l[index+1:]

You could make an iterator out of this if you insist:

def iter_with_others(l):
    for index, item in enumerate(l):
        yield item, l[:index] + l[index+1:]

Giving it's usage:

for item, others in iter_with_others(l):
    print(item, others)
orlp
  • 112,504
  • 36
  • 218
  • 315
  • This works well and is exactly what ecatmur asked for, but seems an exercise in gratuitous list creation. It could perform quite badly with larger lists. I wonder if it might be better to create some sort of wrapper object that provides a view into the original list. – Steven Rumbalski Aug 31 '12 at 20:29
  • @StevenRumbalski: yes, but I'll leave this as an excercise for the reader unless there is a huge demand. – orlp Aug 31 '12 at 20:33
3

Answering my own question, it is possible to use itertools.combinations exploiting the fact that the result is emitted in lexicographical order:

from itertools import combinations
zip(l, combinations(reversed(l), len(l) - 1))

However, this is fairly obscure; nightcracker's solution is a lot easier to understand for the reader!

ecatmur
  • 152,476
  • 27
  • 293
  • 366
2

What about

>>> [(i, [j for j in L if j != i]) for i in L]
[(0, [1, 2, 3]), (1, [0, 2, 3]), (2, [0, 1, 3]), (3, [0, 1, 2])]

OK, that's a gazillion of tests and @nightcracker's solution is likely more efficient, but eh...

Pierre GM
  • 19,809
  • 3
  • 56
  • 67
  • You could use generator expressions instead of the list comprehensions and thereby avoid creating unnecessary lists as @StevenRumbalski had dreamed about. – Tim Pietzcker Sep 01 '12 at 11:32
  • Yes, I could use a generator for the whole expression, but not for the inner loop: the OP wanted to print lists, not generators.. – Pierre GM Sep 01 '12 at 11:38
  • Right, at least in his example. The question is whether that is really what he wants to do with the results. But he can decide that for himself. – Tim Pietzcker Sep 01 '12 at 11:41