views:

230

answers:

3

I have the following code:

items = ["one", "two", "three"]

for i in range(0, len(items)):
    for index, element in enumerate(items):
        if index != i:
            # do something with element

Basically I want to exclude every element once and iterate the rest. So for the list I have above, I'd like the following iterations:

  1. "two", "three"
  2. "one", "three"
  3. "one", "two"

The code I've written now seems a little C++-ish, is there a better solution? (I do not want to hold all possible lists in a variable)

EDIT: I didn't state this but the lists size isn't necessarily 3. It can be of any size.

EDIT 2: It seems there's another misunderstanding: if I have a list of N, then I want N lists of size N-1, each missing an element from the original list.

EDIT 3: A list with 4 items, should give this result:

  1. 1, 2, 3
  2. 1, 3, 4
  3. 1, 2, 4
  4. 2, 3, 4
+14  A: 

Although upvoted like crazy, my first solution wasn't what the OP wanted, which is N lists, each missing exactly one of the N original elements:

>>> from itertools import combinations
>>> L = ["one", "two", "three", "four"]
>>> for R in combinations(L, len(L) - 1):
...     print " and ".join(R)
...
one and two and three
one and two and four
one and three and four
two and three and four

See the revision history for the source of the discussion below.

balpha
But the list I had written was just an example. In practice it can be of size N.
roger
This is much more explicit and clear than the initial code, so I think it qualifies as better? At the very least this is more pythonic.
donut
actually no, I want to iterate all "combinations" of length `N-1`.
roger
@roger: You still want all combinations of length 2
balpha
It really is. Fair enough, you get my sheepish +1.
Jason Orendorff
Okay, I'm in an edit war with myself right now -- sitting back to think for a moment.
balpha
Corrected now. It's permutations, not combinations.
balpha
please read my edit, I still think you got it backwards. Shouldn't `combinations(L, len(L) - 1)` do it?
roger
I accepted your answer although @SilentGhost had the right solution before (maybe inspired by yours). But since you corrected it and your answer has more upvotes it seems more appropriate. Thanks!
roger
+5  A: 
[items[:i]+items[i+1:] for i in range(len(items))]

in py2.x use xrange. obviously, slicing all the time on a big sequence is not very efficient, but it's fine for short ones. Better option would be using itertools.combinations:

>>> for a in itertools.combinations(items, len(items)-1):
    print(a)

('one', 'two')
('one', 'three')
('two', 'three')
SilentGhost
+1  A: 

As roger predicted, an answer which doesn't really improve the existing code :)

a = ["one", "two", "three"]
for i in range(0, len(a)):
  print [val[1] for val in enumerate(a) if val[0] != i]
extraneon