Length-wise-sorted list but, same length in alphab

2020-02-11 05:05发布

问题:

My Python List of string is something like x but long enough:

x = ['aaa','ab','aa','c','a','b','ba']      

I wants to sort this list as: ['a', 'b', 'c', 'aa', 'ab', 'ba', 'aaa'] and I did as follows in two steps:

>>> x.sort()   
>>> x.sort(key=len)      
>>> x
['a', 'b', 'c', 'aa', 'ab', 'ba', 'aaa']   

But I need in one-step: I also tied using lambda function (taken help):

>>> x.sort(key=lambda item: (item, len(item)))
>>> x
['a', 'aa', 'aaa', 'ab', 'b', 'ba', 'c']  

But not as I desired:

Is it possible in one-step? Please me.

My Python:

~$ python --version  
Python 2.6.6

回答1:

You got the order of the tuple the wrong way round. When Python sorts on tuples, the first value is the main sort, with the second being the subsort, etc... - your code presumes the opposite order.

You want to sort by length, then alphabetically:

>>> x.sort(key=lambda item: (len(item), item))
>>> x
['a', 'b', 'c', 'aa', 'ab', 'ba', 'aaa']

Edit: As DSM points out in the comments, Python sorts letters as capitals first, then lowercase. If this behaviour isn't wanted, see this answer.



回答2:

using itertools.grouby():

In [29]: lis = ['aaa','ab','aa','c','a','b','ba']
In [30]: list(chain(*[sorted(g) for k,g in groupby(sorted(lis,key=len),key=len)]))
Out[30]: ['a', 'b', 'c', 'aa', 'ab', 'ba', 'aaa']

timeit comparisons:

In [38]: x = ['aaa','ab','aa','c','a','b','ba']*1000

In [39]: random.shuffle(x)

#may be in more tricky test cases this would be fast

In [40]: %timeit sorted(x,key=lambda item: (len(item), item))
100 loops, best of 3: 11.3 ms per loop

In [41]: %timeit list(chain(*[sorted(g) for k,g in groupby(sorted(x,key=len),key=len)]))
100 loops, best of 3: 7.82 ms per loop