possible pairings in a set

R

Ross

I'm new to python and I'm trying to come up with a function that takes
a given number of players in a game and returns all possible unique
pairings. Here's the code I've come up with so far, but I'm not
getting the output I'd like to:

def all_pairings(players):
cleanlist = []
for i in range(players):
cleanlist.append(i)
return cleanlist
start = 0
follow = start +1
finallist = []
while follow <= len(cleanlist)-1:
for player in cleanlist:
mini = cleanlist[start],cleanlist[follow]
finallist.append(mini)
follow +=1
start+=1
return finallist

If I were to execute the function with all_pairings(4), I want to get
the output [[0,1],[0,2],[0,3],[1,2],[1,3],[2,3]. Instead, I get
[0,1,2,3] with the code I currently have. Can you guys help me out?
Also, if my code is considered ugly or redundant by this community,
can you make suggestions to clean it up?
 
B

Benjamin Peterson

Ross said:
Can you guys help me out?

Do you have Python 2.6? If so, it's a solved problem. :)

import itertools
possible_pairings = list(itertools.combinations(players, 2))
 
J

John Posner

Also, if my code is considered ugly or redundant by this community,
Python is pretty mature: if you have a simple, generic problem, the chances
are that someone else has already solved it, packaging the solution in a
library (or "module"). For your job, the "itertools" module includes the
function "combinations":

import itertools
for comb in itertools.combinations([0,1,2,3], 2):
print comb

output:
(0, 1)
(0, 2)
(0, 3)
(1, 2)
(1, 3)
(2, 3)

Note that the output of itertools.combinations() is not a list but an
iterator. If you need the entire list, use the list() function to have the
iterator deliver all the goods at once:

mylist = list(itertools.combinations([0,1,2,3], 2))





E-mail message checked by Spyware Doctor (6.0.0.386)
Database version: 5.12110
http://www.pctools.com/en/spyware-doctor-antivirus/
 
D

Dave Angel

Ross said:
I'm new to python and I'm trying to come up with a function that takes
a given number of players in a game and returns all possible unique
pairings. Here's the code I've come up with so far, but I'm not
getting the output I'd like to:

def all_pairings(players):
cleanlist = []
for i in range(players):
cleanlist.append(i)
return cleanlist
start = 0
follow = start +1
finallist = []
while follow <= len(cleanlist)-1:
for player in cleanlist:
mini = cleanlist[start],cleanlist[follow]
finallist.append(mini)
follow +=1
start+=1
return finallist

If I were to execute the function with all_pairings(4), I want to get
the output [[0,1],[0,2],[0,3],[1,2],[1,3],[2,3]. Instead, I get
[0,1,2,3] with the code I currently have. Can you guys help me out?
Also, if my code is considered ugly or redundant by this community,
can you make suggestions to clean it up?
First problem is the return you have in the middle of the function,
which returns cleanlist. That's why you're getting [0, 1, 2, 3]

Once you fix that, you'll find you have exceptions in the code where
cleanlist[follow] doesn't work if follow is equal to 4.

I'm afraid the code is ugly, and therefore hard to understand or fix.
Let me suggest an approach, rather than just giving you the code. Why
not create a nested for which generates two subscripts between 0 and 4,
then append only those pairs in which the second is strictly greater
than the first. It won't be the quickest, but it will be easy to follow.

No while loop, no explicit incrementing of variables, and in fact no
subscripting of the lists. Just let them supply their own values.
cleanlist = range(players) # no need for any loop,
it's already a list (except in Python 3.0, in which case it's a sequence
that still works just as well)
finallist = []
for i .....:
for j...
if i<j:
append ...
return finallist
 
M

MRAB

Dave said:
I'm new to python and I'm trying to come up with a function that takes
a given number of players in a game and returns all possible unique
pairings. Here's the code I've come up with so far, but I'm not
getting the output I'd like to:

def all_pairings(players):
cleanlist = []
for i in range(players):
cleanlist.append(i)
return cleanlist
start = 0
follow = start +1
finallist = []
while follow <= len(cleanlist)-1:
for player in cleanlist:
mini = cleanlist[start],cleanlist[follow]
finallist.append(mini)
follow +=1
start+=1
return finallist

If I were to execute the function with all_pairings(4), I want to get
the output [[0,1],[0,2],[0,3],[1,2],[1,3],[2,3]. Instead, I get
[0,1,2,3] with the code I currently have. Can you guys help me out?
Also, if my code is considered ugly or redundant by this community,
can you make suggestions to clean it up?
First problem is the return you have in the middle of the function,
which returns cleanlist. That's why you're getting [0, 1, 2, 3]

Once you fix that, you'll find you have exceptions in the code where
cleanlist[follow] doesn't work if follow is equal to 4.

I'm afraid the code is ugly, and therefore hard to understand or fix.
Let me suggest an approach, rather than just giving you the code. Why
not create a nested for which generates two subscripts between 0 and 4,
then append only those pairs in which the second is strictly greater
than the first. It won't be the quickest, but it will be easy to follow.

No while loop, no explicit incrementing of variables, and in fact no
subscripting of the lists. Just let them supply their own values.
cleanlist = range(players) # no need for any loop, it's
already a list (except in Python 3.0, in which case it's a sequence that
still works just as well)
finallist = []
for i .....:
for j...
if i<j:
append ...
return finallist
Actually, cleanlist == i, so it's pointless. You can do just:

finallist = []
for i in range(players):
for j in range(i + 1, players):
finallist.append((i, j))

or, using list comprehension:

finallist = [(i, j) for i in range(players) for j in range(i + 1,
players)]
 
D

Dave Angel

MRAB said:
Dave said:
I'm new to python and I'm trying to come up with a function that takes
a given number of players in a game and returns all possible unique
pairings. Here's the code I've come up with so far, but I'm not
getting the output I'd like to:

def all_pairings(players):
cleanlist = []
for i in range(players):
cleanlist.append(i)
return cleanlist
start = 0
follow = start +1
finallist = []
while follow <= len(cleanlist)-1:
for player in cleanlist:
mini = cleanlist[start],cleanlist[follow]
finallist.append(mini)
follow +=1
start+=1
return finallist

If I were to execute the function with all_pairings(4), I want to get
the output [[0,1],[0,2],[0,3],[1,2],[1,3],[2,3]. Instead, I get
[0,1,2,3] with the code I currently have. Can you guys help me out?
Also, if my code is considered ugly or redundant by this community,
can you make suggestions to clean it up?
First problem is the return you have in the middle of the function,
which returns cleanlist. That's why you're getting [0, 1, 2, 3]

Once you fix that, you'll find you have exceptions in the code where
cleanlist[follow] doesn't work if follow is equal to 4.

I'm afraid the code is ugly, and therefore hard to understand or
fix. Let me suggest an approach, rather than just giving you the
code. Why not create a nested for which generates two subscripts
between 0 and 4, then append only those pairs in which the second is
strictly greater than the first. It won't be the quickest, but it
will be easy to follow.

No while loop, no explicit incrementing of variables, and in fact no
subscripting of the lists. Just let them supply their own values.
cleanlist = range(players) # no need for any loop,
it's already a list (except in Python 3.0, in which case it's a
sequence that still works just as well)
finallist = []
for i .....:
for j...
if i<j:
append ...
return finallist
Actually, cleanlist == i, so it's pointless. You can do just:

finallist = []
for i in range(players):
for j in range(i + 1, players):
finallist.append((i, j))

or, using list comprehension:

finallist = [(i, j) for i in range(players) for j in range(i + 1,
players)]


This looked to me like a homework assignment, or a self-assignment for a
relative beginner in Python. So I wanted to outline an approach, not
provide the absolute optimum answer which might not be understood. I
avoided mentioning the itertools.combinations() function because you
can't learn much from a single function call. I avoided list
comprehensions because they are very hard for many inexperienced python
programmers.

I left the cleanlist in because this approach can be readily generalized
to taking a list which isn't just a list of numbers. Add an enumerate
to each of the for loops, and you can readily produce all the
combinations of whatever might be in the first list.

I debated with myself using slicing of the list for the nested for (your
range(i+1, players) is equivalent to a slice), and decided that it would
be harder to read. . Clearly my nested loop iterates twice as much on
the average as is needed, but the if is easier to read for a beginner.

Even for experienced developers, sometimes optimizing too early can make
it hard to visualize generalizing a function. If the function took a
list rather than an upperlimit, it would be much more general, but how
many could take your list comprehension and turn it into
def all_pairings(cleanlist):
return [ (a, b) for i, a in enumerate(cleanlist) for b in
cleanlist[i+1:] ]

print all_pairings(range(2,6))
print all_pairings( ("tom", "dick", "harry", "jim") )
 
S

Steven D'Aprano

I'm new to python and I'm trying to come up with a function that takes a
given number of players in a game and returns all possible unique
pairings. Here's the code I've come up with so far, but I'm not getting
the output I'd like to:

Others have already given a solution for Python 2.6, using
itertools.combinations(). Here's a solution for Python 2.4 and 2.5.

The thing to remember about combinations is that they can be defined
recursively. To find the combinations of [1, 2, 3, 4] we can do something
like this:

Combinations of [1, 2, 3, 4]:
Start with the first item, 1.
Combinations are given by [1] + combinations of what's left: [2, 3, 4].

Combinations of [2, 3, 4]:
Start with the first item, 2.
Combinations are given by [2] + combinations of what's left: [3, 4].

Combinations of [3, 4]:
Start with the first item, 3.
Combinations are given by [3] + combinations of what's left: [4].

Combinations of [4]:
Start with the first item, 4.
Combinations are given by [4] + combinations of what's left: [].

Combinations of []:
There aren't any, so we're done.


Using that algorithm gives us this function:

def combinations(seq, r=None):
"""Generator returning combinations of items from sequence <seq>
taken <r> at a time. Order is not significant. If <r> is not given,
the entire sequence is returned.
"""
if r == None:
r = len(seq)
if r <= 0:
yield []
else:
for i in xrange(len(seq)):
for cc in combinations(seq[i+1:], r-1):
yield [seq]+cc


def all_pairings(players):
return list(combinations(range(players), 2))

If I were to execute the function with all_pairings(4), I want to get
the output [[0,1],[0,2],[0,3],[1,2],[1,3],[2,3].
[[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top