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