Please improve these comprehensions (was meaning of [ ])

Rustom Mody rustompmody at gmail.com
Tue Sep 5 09:49:59 EDT 2017


On Tuesday, September 5, 2017 at 6:59:11 PM UTC+5:30, Ben Bacarisse wrote:
> Rustom Mody  writes:
> 
> > On Tuesday, September 5, 2017 at 1:44:24 AM UTC+5:30, Ben Bacarisse wrote:
> >> Rustom Mody  writes:
> >> 
> >> > Here is some code I (tried) to write in class the other day
> >> >
> >> > The basic problem is of generating combinations
> >> <snip>
> >> > Now thats neat as far as it goes but combinations are fundamentally sets
> >> > not lists
> >> >
> >> > So I thought python would do a better job
> >> > I tried translating it to python and sets but it turned out more annoying than
> >> > helpful
> >> > Can someone improve it??
> >> >
> >> > The straightforward translation of the above
> >> > Which is ok so far
> >> >
> >> >
> >> > def c(n,r):
> >> >     if r == 0:
> >> >         return [[]]
> >> >     elif len(n) == 0:
> >> >         return []
> >> >     else:
> >> >         return [[n[0]] + l for l in c(n[1:],r-1)] + c(n[1:],r)
> >> >
> >> >
> >> > Now to go from returning list of lists to set of sets:
> >> 
> >> def cs(n, r):
> >>     if r == 0:
> >>         return [set()]
> >>     elif len(n) == 0:
> >>         return []
> >>     else:
> >>         return [set([n[0]]) | l for l in cs(n[1:], r-1)] + cs(n[1:], r)
> >> 
> >> ?
> >> 
> >> It's not so neat if you also want n to be a set rather than a list
> >> because the set equivalents of n[0] and n[1:] are a but more complex but
> >> it's not that bad:
> >> 
> >> def css(n,r):
> >>     if r == 0:
> >>         return [set()]
> >>     elif len(n) == 0:
> >>         return []
> >>     else:
> >>         rest = n.copy()
> >>         e = rest.pop()
> >>         return [set([e]) | l for l in css(rest, r-1)] + css(rest, r)
> >
> > Trying out your code Ben…
> >
> >>>> css({1,2,3,4}, 2)
> > [set([1, 2]), set([1, 3]), set([1, 4]), set([2, 3]), set([2, 4]), set([3, 4])]
> >
> >>>> type(css({1,2,3,4}, 2))
> > <type 'list'>
> >
> > Whereas with the cs I earlier gave:
> >>>> cs(frozenset([1,2,3,4]), 2)
> > frozenset([frozenset([2, 4]), frozenset([3, 4]), frozenset([2, 3]),
> > frozenset([1, 3]), frozenset([1, 2]), frozenset([1, 4])])
> 
> If you want a (frozen) sets of sets I'd just the code to
> 
> def css(n, r):
>     if r == 0:
>         return frozenset({frozenset()})
>     elif len(n) == 0:
>         return frozenset()
>     else:
>         rest = set(n)
>         e = rest.pop()
>         return frozenset([frozenset([e])
>                           | l for l in list(css(rest, r-1))]) | css(rest, r)
> 
> >>> css(frozenset({1,2,3,4}), 2)
> frozenset({frozenset({2, 4}), frozenset({3, 4}), frozenset({2, 3}),
> frozenset({1, 3}), frozenset({1, 2}), frozenset({1, 4})})
> 
> The switch from lists (using +) and frozen sets using | is the most
> obvious change, but if the top-level argument might itself be a
> frozenset then the copy must be changed to a set constructor so that pop
> will work.

Yes…
Pop et al wont work with frozen sets
Containment wont work with sets — what mathematicians call 'not closed'
All of which amounts to this that python sets are not really pleasant for
math-work

[Just for context: A teacher may have more important things to teach than python
If the niggles get overbearing the vehicle may not be worth it
]

Besides I find the name pop ridiculous
Stacks imply a stronger order usage-discipline than lists
Sets are unordered compared to lists
To use a name traditionally reserved for a stack op on sets is quite nonsensical



More information about the Python-list mailing list