[Tutor] Sorting list of tuples in two passes

Dayo Adewunmi contactdayo at gmail.com
Mon Aug 29 12:12:18 CEST 2011


On 08/29/2011 01:59 AM, Hugo Arts wrote:
> On Mon, Aug 29, 2011 at 2:19 AM, Dayo Adewunmi<contactdayo at gmail.com>  wrote:
>> On 08/28/2011 06:23 PM, Hugo Arts wrote:
>>> On Sun, Aug 28, 2011 at 6:43 PM, Dayo Adewunmi<contactdayo at gmail.com>
>>>   wrote:
>>>> Hi
>>>>
>>>> I have a list of tuples that each have four elements:
>>>>
>>>> [(firstName,lastName,userName,gidNumber),(.....)....]
>>>>
>>>> I'm trying to sort this list in two passes. First by gidNumber and then
>>>> the
>>>> subgroups by lastName. So far i've only been able to sort by gidNumber.
>>>> But
>>>> I can't seem to wrap my mind around lambda, which is what my browsing
>>>> around
>>>> seems to indicate is needed to achieve this?
>>>>
>>>> Thanks
>>>>
>>>> Dayo
>>>>
>>> Python's builtin sort is stable, which means that ordering of items
>>> with the same key is preserved. This property means that you can do
>>> multiple pass sorting very easily and efficiently just by sorting
>>> twice:
>>>
>>>>>> # we'll simplify the problem a bit and have tuples with just last name
>>>>>> and id.
>>>>>> l = [('aaa', 1), ('bbb', 1), ('ccc', 1), ('aaa', 2), ('bbb', 2),
>>>>>> ('ccc', 2)]
>>>>>> l.sort(key=itemgetter(0))
>>>>>> l
>>> [('aaa', 1), ('aaa', 2), ('bbb', 1), ('bbb', 2), ('ccc', 1), ('ccc', 2)]
>>>>>> l.sort(key=itemgetter(1))
>>>>>> l
>>> [('aaa', 1), ('bbb', 1), ('ccc', 1), ('aaa', 2), ('bbb', 2), ('ccc', 2)]
>>> We sort by last name first, then sort again by id. As you can see, the
>>> sorting of groups with the same id is preserved, and our list is now
>>> in the correct order.
>>>
>>> Hugo
>>>
>> It works when I use your example, but I don't understand why it won't work
>> when I use 4-element tuples instead of 2:
>>
>>>>> l = [('wascas','aaa','fdvdfv', 1), ('rtgdsf','bbb','trfg', 1),
>>>>> ('addwe','ccc','esd', 1), ('xasd','aaa','wascaq', 2), ('nhy','bbb','asw',
>>>>> 2), ('zzzz','ccc','dgdeg', 2)]
>>>>> l
>> [('wascas', 'aaa', 'fdvdfv', 1), ('rtgdsf', 'bbb', 'trfg', 1), ('addwe',
>> 'ccc', 'esd', 1), ('xasd', 'aaa', 'wascaq', 2), ('nhy', 'bbb', 'asw', 2),
>> ('zzzz', 'ccc', 'dgdeg', 2)]
>>>>> l.sort(key=itemgetter(3))
>>>>> l
>> [('wascas', 'aaa', 'fdvdfv', 1), ('rtgdsf', 'bbb', 'trfg', 1), ('addwe',
>> 'ccc', 'esd', 1), ('xasd', 'aaa', 'wascaq', 2), ('nhy', 'bbb', 'asw', 2),
>> ('zzzz', 'ccc', 'dgdeg', 2)]
>>>>> l.sort(key=itemgetter(1))
>>>>> l
>> [('wascas', 'aaa', 'fdvdfv', 1), ('xasd', 'aaa', 'wasca    q', 2),
>> ('rtgdsf', 'bbb', 'trfg', 1), ('nhy', 'bbb', '
>> asw', 2), ('addwe', 'ccc', 'esd', 1), ('zzzz', 'ccc', 'dgdeg', 2)]
>>
>> Also I notice your original list and your end result list are in the same
>> order.
>>
>> Thanks
>>
>> Dayo
>>
> In my original example, you can shuffle the list before you sort it
> and it will still work. Try it, with a quick "from random import
> shuffle; shuffle(l)".
>
> Also, notice that you want to sort by your primary order *last*. I
> sorted by last name first, then sorted by id second, which means the
> final list's primary order is by id, and secondary order by last name.
> So the sorting goes in reverse. In your example, you sort by id first,
> then last name. So your final list's primary order is by last name.
>
> Hugo
>
I tried it this way and it worked nicely:
sortedList = sorted(l, key = itemgetter(3,1))

Thank you :-)

Dayo


More information about the Tutor mailing list