Search code examples
pythonsortinglambda

Deconstructing a tuple when using sorted with lambda function on key


I work with frequencies (%) and entropy (bits). Those two realities are very similar and it's very easy to mix them up.

When I have tuples of frequency/entropy, I ALWAYS name the tuple members so my code is easier to understand.

I am struggling to find a solution for the function sorted(). Just check the code below:

import math

def entropy(probability: float) -> float:
    if probability == 0: return 0
    else: return -probability*math.log(probability)/math.log(2)

pairs = [(frequency/10, entropy(frequency/10)+entropy(1-frequency/10)) for frequency in range(11)]
print(pairs)
print(sorted(pairs, key=lambda f, e: -e * 1000 + f))

I would really love to be able to write the lambda function with two arguments f and e, but my Python keeps saying there is a syntax error there: No overloads for "sorted" match the provided arguments.

Is there a way to do this in Python or should I give into a @dataclass like this:

@dataclass
class Pair:
    frequency: float = 0.0
    uncertainty: float = 0.0

Solution

  • If you want to name both elements of your tuple, you can use a namedtuple instead of a conventional tuple.

    from collections import namedtuple
    import math
    
    f_S = namedtuple("f_S", ["frequency", "entropy"])
    
    def entropy(probability: float) -> float:
        if probability == 0: return 0
        else: return -probability*math.log(probability)/math.log(2)
    
    pairs = [f_S(frequency/10, entropy(frequency/10)+entropy(1-frequency/10)) for frequency in range(11)]
    print("pairs:", pairs)
    print("sorted:", sorted(pairs, key=lambda fS: -fS.entropy * 1000 + fS.frequency))
    

    Output:

    pairs: [f_S(frequency=0.0, entropy=0.0), f_S(frequency=0.1, entropy=0.4689955935892812), f_S(frequency=0.2, entropy=0.7219280948873623), f_S(frequency=0.3, entropy=0.8812908992306927), f_S(frequency=0.4, entropy=0.9709505944546688), f_S(frequency=0.5, entropy=1.0), f_S(frequency=0.6, entropy=0.9709505944546688), f_S(frequency=0.7, entropy=0.8812908992306927), f_S(frequency=0.8, entropy=0.7219280948873623), f_S(frequency=0.9, entropy=0.46899559358928117), f_S(frequency=1.0, entropy=0.0)]
    sorted: [f_S(frequency=0.5, entropy=1.0), f_S(frequency=0.4, entropy=0.9709505944546688), f_S(frequency=0.6, entropy=0.9709505944546688), f_S(frequency=0.3, entropy=0.8812908992306927), f_S(frequency=0.7, entropy=0.8812908992306927), f_S(frequency=0.2, entropy=0.7219280948873623), f_S(frequency=0.8, entropy=0.7219280948873623), f_S(frequency=0.1, entropy=0.4689955935892812), f_S(frequency=0.9, entropy=0.46899559358928117), f_S(frequency=0.0, entropy=0.0), f_S(frequency=1.0, entropy=0.0)]