osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Please improve these comprehensions (was meaning of [ ])


Rustom Mody <rustompmody at gmail.com> 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.

<snip>
-- 
Ben.