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
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.
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