Reputation: 279285
The following appears in my Python 2.6 code:
for src, dst in ([s,d] for s in universe for d in universe if s != d):
Can I do much better? What I particularly don't like is that I'm in effect specifying the same pair twice, once for the for loop and again for the generator expression. I'm uncertain whether I'd prefer:
for src, dst in itertools.product(universe, universe):
if src != dst:
Is there a way to express this loop concisely?
universe
happens to be a list, if it makes any difference. Order of iteration doesn't matter.
Upvotes: 8
Views: 912
Reputation: 26552
itertools.product can take a "repeat" keyword argument if you want to have the same sequence as more than one parameter:
itertools.product(universe, repeat=2)
it is a matter of opinion as to whether this is more readable.
You could replace your original code with:
for (src, dest) in filter(lambda (a,b): a!=b, itertools.product(universe, repeat=2)):
...
Upvotes: 1
Reputation: 42689
I suggest keeping it entirely functional or entirely with comprehensions. Here's an implementation that's entirely functional.
import itertools
import operator
def inner_product(iterable):
"the product of an iterable with itself"
return itertools.product(iterable, repeat=2)
def same(pair):
"does this pair contain two of the same thing?"
return operator.is_(*pair)
universe = 'abcd'
pairs = inner_product(universe)
unique_pairs = itertools.ifilterfalse(same, pairs)
for pair in unique_pairs:
print pair
"""
('a', 'b')
('a', 'c')
('a', 'd')
('b', 'a')
('b', 'c')
('b', 'd')
('c', 'a')
('c', 'b')
('c', 'd')
('d', 'a')
('d', 'b')
('d', 'c')
"""
Upvotes: 3
Reputation: 229663
You could use simple nested for-loops:
for src in universe:
for dst in universe:
if src == dst:
continue
...
I'd say this is the most easy to read syntax in this case.
Upvotes: 5