Search code examples
pythonpython-3.xsortingindexingtuples

Why does this sorted key lambda encounter an IndexError


I thought I understood the key argument for the sorted function, but for the life of me, I cannot figure out why it appears to be applying the tuple index to the string inside the tuple instead of to the tuple? What is going on here? I'm running python 3.9.

I narrowed it down to this toy example:

sorted([val[0] for val in [('C', 'C')]], key=lambda tpl: tpl[1])

Error message:

In [11]: sorted([val[0] for val in [('C', 'C')]], key=lambda tpl: tpl[1])
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-11-53d87bf797aa> in <module>
----> 1 sorted([val[0] for val in [('C', 'C')]], key=lambda tpl: tpl[1])

<ipython-input-11-53d87bf797aa> in <lambda>(tpl)
----> 1 sorted([val[0] for val in [('C', 'C')]], key=lambda tpl: tpl[1])

IndexError: string index out of range

If I don't supply the key argument, it works just fine:

In [12]: sorted([val[0] for val in [('C', 'C')]])
Out[12]: ['C']

I just want to sort by the second item in the tuple.


Solution

  • You are currently sorting the result of the list comprehension, but what you want is to execute the comprehension after you sort the results. If we reformat your line you will see it more clearly:

    sorted(
        [
            val[0] for val in [('C', 'C')]
        ], 
        key=lambda tpl: tpl[1]
    )
    

    You should simply reorder it:

    [
        val[0]
        for val in sorted(
            [('1', 'C'), ('2', 'A'), ('3', 'B')],
            key=lambda tpl: tpl[1]
        )
    ]
    

    Output:

    ['2', '3', '1']