ryanvolap
ryanvolap

Reputation: 77

Pairing elements in a nested list

I have a list of lists like this.

a = [1, 2, 3, 4]
b = [3, 2, 0.3]
c = [0.1, 3, 6.8]
d = [9, 2.5, 7, 2]

x = [a, b, c, d]

I want to pair them like this:

[a, b], [b, a], [a, c], [c, a], [a, d], [d, a], [b, c], [c, b], [b, d], [d, b], [c, d], [d, c]

This is the way I do it:

for i in range(len(x)):
    for j in range(len(x):
         if i!= j:
             #TODO...
             print(x[i], x[j])

My question is: Is there a smarter way to do it to improve performance? ( When x has 6-7 items, I can tell it slowing down a lot).

Any of your inputs would help me a lot.

Thanks

Upvotes: 2

Views: 374

Answers (3)

Netwave
Netwave

Reputation: 42746

Use itertools.permutations:

a = [1, 2, 3, 4]
b = [3, 2, 0.3]
c = [0.1, 3, 6.8]
d = [9, 2.5, 7, 2]
x = [a, b, c, d]
import itertools
list(itertools.permutations(x, 2))
[([1, 2, 3, 4], [3, 2, 0.3]), ([1, 2, 3, 4], [0.1, 3, 6.8]), ([1, 2, 3, 4], [9, 2.5, 7, 2]), ([3, 2, 0.3], [1, 2, 3, 4]), ([3, 2, 0.3], [0.1, 3, 6.8]), ([3, 2, 0.3], [9, 2.5, 7, 2]), ([0.1, 3, 6.8], [1, 2, 3, 4]), ([0.1, 3, 6.8], [3, 2, 0.3]), ([0.1, 3, 6.8], [9, 2.5, 7, 2]), ([9, 2.5, 7, 2], [1, 2, 3, 4]), ([9, 2.5, 7, 2], [3, 2, 0.3]), ([9, 2.5, 7, 2], [0.1, 3, 6.8])]

As comment say, for the specific order you can use itertools.combinations:

list(itertools.chain.from_iterable(map(lambda x: (x, x[::-1]), 
                                       itertools.combinations(x, 2))))
[([1, 2, 3, 4], [3, 2, 0.3]), ([3, 2, 0.3], [1, 2, 3, 4]), ([1, 2, 3, 4], [0.1, 3, 6.8]), ([0.1, 3, 6.8], [1, 2, 3, 4]), ([1, 2, 3, 4], [9, 2.5, 7, 2]), ([9, 2.5, 7, 2], [1, 2, 3, 4]), ([3, 2, 0.3], [0.1, 3, 6.8]), ([0.1, 3, 6.8], [3, 2, 0.3]), ([3, 2, 0.3], [9, 2.5, 7, 2]), ([9, 2.5, 7, 2], [3, 2, 0.3]), ([0.1, 3, 6.8], [9, 2.5, 7, 2]), ([9, 2.5, 7, 2], [0.1, 3, 6.8])]

Upvotes: 4

Yinon
Yinon

Reputation: 955

you can try zip:

a = [1,2,3]
b = [4,5,6]
c = [7,8,9]
x = [a,b,c]
y = []
for i in range (0,len(x)):
    for j in range (i + 1, len(x)):
        y.append(zip(x[i],x[j]))
        y.append(zip(x[j],x[i]))
print y

Upvotes: 0

cs95
cs95

Reputation: 402814

This comment gave me an interesting idea. Here it is, using itertools.combinations, which returns items in the order you're looking for.

from itertools import combinations

def foo(x):
     for x in combinations(x, 2):
         yield from (x, x[::-1]) # python3.3+ 


for i in foo(['a', 'b', 'c', 'd']):
    print(i)

('a', 'b')
('b', 'a')
('a', 'c')
('c', 'a')
('a', 'd')
('d', 'a')
('b', 'c')
('c', 'b')
('b', 'd')
('d', 'b')
('c', 'd')
('d', 'c')

Replace ['a', 'b', 'c', 'd'] with [a, b, c, d], which is your actual list of lists.


Note: On python <3.3, you'd need yield x; yield x[::-1], because yield from isn't supported.

Upvotes: 4

Related Questions