tags:

views:

139

answers:

6

I have a list of users:

users = [1,2,3,4,5]

I want to compute a relationship between them:

score = compatibility( user[0], user[1] )

How do I loop over users so that a relationship between users are computed only once?

A: 

use for loops, or list comprehension.

here is for loop example:

for u in users:
    for su in users:
        if su == u:
            pass
        else:
            score = compatibility(u, su)
            # do score whatever you want

list comprehension:

score = [compatibility(x, y) for x in users for y in users if x!=y and compatibility(x,y) not in score]
Mohamed
compatibility looks like a commutative operation. In that case, you're computing compatibility of each user pair twice, once as compatibility(A,B) and again as compatibility(B,A).
bendin
@bendin, yup correct but adding compatibility(x,y) not in score will make sure that there will be only one relationship in the pair.
Mohamed
+11  A: 

If you care only about ordered relationship, you could do the following:

>>> for i, u in enumerate(users[1:]):
    print(users[i], u)           # or do something else


1 2
2 3
3 4
4 5

if you need all combinations you should use itertools.combinations:

>>> import itertools
>>> for i in itertools.combinations(users, 2):
    print(*i)

1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
SilentGhost
+1 for showing me another Python function I didn't know existed :).
Andre Miller
`itertools` is full of gems ;)
SilentGhost
>for i in itertools.combinations(users, 2):Very elegant! Thank you for this solution!
Hobhouse
`itertools.combinations` yields all _combinations_, not _permutations_. `itertools.permutations` would yield `(1,2)` and `(2,1)`.
Alasdair
@Alasdair: and it's exactly what the OP doesn't need.
SilentGhost
@SilentGhost: I wasn't trying to suggest that the OP needed `permutations`. I commented in response to your wording "if you need all permutation", because I think 'combinations' would be more precise.
Alasdair
@Alasdair: thanks, well noticed.
SilentGhost
A: 

Something like the following should work (not tested):

users_range = range(len(users))

# Initialize a 2-dimensional array
scores = [None for j in users_range for i in users_range]

# Assign a compatibility to each pair of users.
for i in users_range:
    for j in users_range:
        scores[i][j] = compatibility(users[i], users[j])
Fragsworth
A: 

I managed to do what I wanted with this:

i = 0
for user1 in users:   
    i += 1     
    for user2 in users[i:]:
        print compatibility( user1, user2 )
Hobhouse
A: 

If you mean that:

compatibility(user[0], user[1]) == compatibility(user[1], user[0])

you could use:

for i, user1 in enumerate(users):
    for user2 in users[i:]:
        score = compatibility(user1, user2)

this will also calculate the compatibility between the same users (maybe applicable)

Wim Verhavert
A: 
import itertools

def compatibility(u1, u2):
    "just a stub for demonstration purposes"
    return abs(u1 - u2)

def compatibility_map(users):
    return dict(((u1, u2), compatibility(u1, u2))
         for u1, u2 in itertools.combinations(users, 2))

> compat.compatiblity_map([1,2,3,4,5])
{(1, 2): 1, (1, 3): 2, (4, 5): 1, (1, 4): 3, (1, 5): 4,
 (2, 3): 1, (2, 5): 3, (3, 4): 1, (2, 4): 2, (3, 5): 2}

Use itertools.permuations instead of itertools.combinations if compatibility(a,b) doesn't mean the same thing as compatibility(b,a).

bendin