Some thougts on cartesian products
Steven D'Aprano
steve at REMOVETHIScyber.com.au
Sun Jan 22 14:50:13 EST 2006
On Sun, 22 Jan 2006 19:12:49 +0100, Christoph Zwerschke wrote:
> Steven D'Aprano wrote:
>> On Sun, 22 Jan 2006 18:29:45 +0100, Christoph Zwerschke wrote:
>>> For doing such things I would use a vector subtype of list.
>>
>> Not everything needs to be a separate class! Why create a magic class for
>> every piece of functionality you want? Just create functions that operate
>> on existing classes!
> >
> > What advantage is there to creating a "list with cartesian product"
> > subclass of list?
>
> Principally, you're right (see also my example with iterators).
>
> But I can still see two reasons for classes:
>
> 1) That function would have to make a lot of case distinctions (check
> the types of operands). If you have a class, you already know the type
> of the operands (at least one).
If you are happy to always return a list of tuples regardless of what the
two operands are, generators make it so easy it is shameful. Even if you
want a special case of two string arguments returning a string, it is
hardly any more difficult:
def cartprod(A, B):
if type(A) == type(B) == str:
convert = lambda obj: "".join(list(obj))
else:
convert = lambda obj: obj # do nothing
for a in A:
for b in B:
yield convert((a, b))
Notice that the *only* reason we look at the type of the arguments is
because we want two strings to return a string. If we don't care about
that, the generator is less than half the size:
def cartprod(A, B):
for a in A:
for b in B:
yield (a, b)
That's a generator giving you the products one at a time. For the
benefit of anyone out there who doesn't know about generators, you use it
like this:
>>> cprods = cartprod([1,2,3], "abc")
>>> for t in cprods:
... print t
...
(1, 'a')
(1, 'b')
(2, 'a')
(2, 'b')
(3, 'a')
(3, 'b')
If you want them all at once, memory allowing, you do this:
>>> cprods = cartprod([1,2,3], "abc")
>>> list(cprods)
[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b')]
> 2) It allows you to write a*b instead of mul(a,b) which looks nicer.
But not as clear as cartprod(a,b) or even cartesian_product(a,b).
--
Steven.
More information about the Python-list
mailing list