按长度排序的列表,但同样长度按字母顺序在一步中

6

我的Python字符串列表类似于x,但足够长:

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

我希望将此列表按以下方式排序:['a', 'b', 'c', 'aa', 'ab', 'ba', 'aaa'],我分两步进行如下操作:

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

但我需要一步完成:我也尝试使用 lambda 函数(参考):

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

但并非我所期望的:

有没有一步到位的方法?请帮忙。

我的Python:

~$ python --version  
Python 2.6.6

我将 python-2.7 标签编辑为 python-2.6,因为你明确表示正在使用 2.6 版本。 - Gareth Latty
2个回答

9

您将元组的顺序搞反了。当Python对元组进行排序时,第一个值是主要排序,第二个值是次要排序,以此类推......您的代码假定相反的顺序。

您想按长度排序,然后按字母顺序排序:

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

编辑:正如 DSM 在评论中指出的那样,Python 对字母的排序是先大写字母,然后小写字母。如果不想要这种行为,请参见此答案


实际上,由于大小写问题,它并不能按字母顺序排序(但这很容易修复)。[我承认OP的列表目前都是小写。] - DSM
@DSM 我在模拟原始 - 据说是 - 工作代码的行为,大写字母可能会先出现,但这可能是期望的行为,不清楚。 - Gareth Latty
@Lattyware:我的工作完成了,我也明白了。但是还有一个疑问,第一个两步解决方案是如何工作的?我按字母顺序排序,然后按长度排序!这就是我无法想到你尝试过什么的原因。 - Grijesh Chauhan
1
你的第一个解决方案有效是因为当Python按键排序时,如果值相等,则进行稳定排序 - 即相等值的顺序是它们在输入中的顺序。这意味着如果您按一个值排序,然后按另一个值排序,第一个排序将作为子排序 穿透 - Gareth Latty
@Lattyware 我在 Python 书中读了很多次关于“稳定排序”的术语,但今天我终于理解了它的含义。谢谢,现在我完全明白了。 - Grijesh Chauhan

1

使用 itertools.groupby()

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 比较:

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

2
这似乎过于复杂了。虽然不是错的,但我真的看不出它的价值所在。 - Gareth Latty
1
我和下一个人一样喜欢 itertools,但这太疯狂了!PS:你不需要使用 list 函数,sorted 函数会消耗 g 并生成一个列表。 - DSM
@DSM 忘记删除 list() 调用,只是为了测试目的使用它。我知道这与 lattyware 的答案相比有些奇怪,但在性能方面,这种方法更快。 - Ashwini Chaudhary
1
@AshwiniChaudhary 不错的模拟..这种能力非常好且必要..再次感谢! - Grijesh Chauhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接