Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 自然地对列表进行排序,将字母数字值移动到末尾_Python_Sorting_Natural Sort - Fatal编程技术网

Python 自然地对列表进行排序,将字母数字值移动到末尾

Python 自然地对列表进行排序,将字母数字值移动到末尾,python,sorting,natural-sort,Python,Sorting,Natural Sort,我有一个要自然排序的字符串列表: c = ['0', '1', '10', '11', '2', '2Y', '3', '3Y', '4', '4Y', '5', '5Y', '6', '7', '8', '9', '9Y'] 除了自然排序之外,我还希望将所有不是纯数字字符串的条目移到末尾。我的预期输出是: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '2Y', '3Y', '4Y', '5Y', '9Y']

我有一个要自然排序的字符串列表:

c = ['0', '1', '10', '11', '2', '2Y', '3', '3Y', '4', '4Y', '5', '5Y', '6', '7', '8', '9', '9Y']
除了自然排序之外,我还希望将所有不是纯数字字符串的条目移到末尾。我的预期输出是:

['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '2Y', '3Y', '4Y', '5Y', '9Y']
请注意,所有内容都必须进行排序,即使是字母数字字符串

我知道我可以使用
natsort
软件包来获得我想要的东西,但单凭这一点并不能满足我的需要。我需要通过两个排序调用来实现这一点——一个调用自然排序,另一个调用将非纯数字字符串移到末尾

import natsort as ns
r = sorted(ns.natsorted(c), key=lambda x: not x.isdigit())

print(r)
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '2Y', '3Y', '4Y', '5Y', '9Y']

我想知道是否可以巧妙地使用
natsort
,并将其简化为单个排序调用

natsort
有一个函数
natsort\u键
,它将项转换为元组,并根据元组进行排序

因此,您可以将其用作:

sorted(c, key=lambda x: (not x.isdigit(), *ns.natsort_key(x)))
您也可以在不使用iterable解包的情况下使用它,因为在这种情况下,我们有两个2元组,如果第一个项目出现平局,它将因此比较
natsort\u键的结果
调用:

sorted(c, key=lambda x: (not x.isdigit(), ns.natsort_key(x)))

我很感谢威廉·范·昂森发布了他的答案。但是,我应该注意到,原始函数的性能要快一个数量级。考虑到PM2环的建议,以下是两种方法之间的一些基准:

设置

c = \
['0',
 '1',
 '10',
 '11',
 '2',
 '2Y',
 '3',
 '3Y',
 '4',
 '4Y',
 '5',
 '5Y',
 '6',
 '7',
 '8',
 '9',
 '9Y']
d = c * (1000000 // len(c) + 1)  # approximately 1M elements

对原版高性能的解释是因为Tim Sort似乎对几乎排序的列表进行了高度优化


健全性检查

x = sorted(d, key=lambda x: (not x.isdigit(), ns.natsort_key(x)))
y = sorted(ns.natsorted(d), key=str.isdigit, reverse=True)

all(i == j for i, j in zip(x, y))
True

实际上,您可以使用
natsorted
和正确选择
键来执行此操作

>>> ns.natsorted(d, key=lambda x: (not x.isdigit(), x))
['0',
 '1',
 '2',
 '3',
 '4',
 '5',
 '6',
 '7',
 '8',
 '9',
 '10',
 '11',
 '2Y',
 '3Y',
 '4Y',
 '5Y',
 '9Y']
In [13]: %timeit sorted(d, key=lambda x: (not x.isdigit(), ns.natsort_key(x)))
1 loop, best of 3: 33.3 s per loop

In [14]: natsort_key = ns.natsort_keygen()

In [15]: %timeit sorted(d, key=lambda x: (not x.isdigit(), natsort_key(x)))
1 loop, best of 3: 11.2 s per loop

In [16]: %timeit sorted(ns.natsorted(d), key=str.isdigit, reverse=True)
1 loop, best of 3: 9.77 s per loop

In [17]: %timeit ns.natsorted(d, key=lambda x: (not x.isdigit(), x))
1 loop, best of 3: 23.8 s per loop
键返回一个元组,原始输入作为第二个元素。数字字符串放在前面,所有其他字符串放在后面,然后对子集进行单独排序

作为旁注,使用
natsort\u键
,该键在
natsort
3.0.4版时已被弃用(如果在解释器中打开
弃用警告
,您将看到该键,并且该函数现在未被记录)。实际上效率很低。。。最好使用返回自然排序键的
natort\u keygen
natsort_key
在引擎盖下调用此函数,因此对于每个输入,您都创建一个新函数,然后调用它一次

下面我重复所示的测试,并使用
natsort
方法添加我的解决方案,以及使用
natsort\u-keygen
而不是
natsort\u-key
添加其他解决方案的计时

>>> ns.natsorted(d, key=lambda x: (not x.isdigit(), x))
['0',
 '1',
 '2',
 '3',
 '4',
 '5',
 '6',
 '7',
 '8',
 '9',
 '10',
 '11',
 '2Y',
 '3Y',
 '4Y',
 '5Y',
 '9Y']
In [13]: %timeit sorted(d, key=lambda x: (not x.isdigit(), ns.natsort_key(x)))
1 loop, best of 3: 33.3 s per loop

In [14]: natsort_key = ns.natsort_keygen()

In [15]: %timeit sorted(d, key=lambda x: (not x.isdigit(), natsort_key(x)))
1 loop, best of 3: 11.2 s per loop

In [16]: %timeit sorted(ns.natsorted(d), key=str.isdigit, reverse=True)
1 loop, best of 3: 9.77 s per loop

In [17]: %timeit ns.natsorted(d, key=lambda x: (not x.isdigit(), x))
1 loop, best of 3: 23.8 s per loop

为什么要担心执行第二种排序?TimSort针对包含已排序子序列的排序序列进行了优化,因此第二次排序将非常快。您可以通过消除lambda来提高性能:
key=str.isdigit,reverse=True
@PM2Ring如果您能详细阐述一下并将其转化为答案,我将不胜感激!嗯,这是一个3.6版本的函数吗?@cᴏʟᴅsᴘᴇᴇᴅ: 不,我设法让它在Python-3.5.3中工作。Natsort是5.1.0。我的错,iterable解包是python3.5+(我在4)。这不是问题。@cᴏʟᴅsᴘᴇᴇᴅ: 事实上,我不认为解包是必要的,因为它会递归地对元素进行排序。没错,但是如果你在key函数中展平元组,解包可能会稍微快一点。
In [13]: %timeit sorted(d, key=lambda x: (not x.isdigit(), ns.natsort_key(x)))
1 loop, best of 3: 33.3 s per loop

In [14]: natsort_key = ns.natsort_keygen()

In [15]: %timeit sorted(d, key=lambda x: (not x.isdigit(), natsort_key(x)))
1 loop, best of 3: 11.2 s per loop

In [16]: %timeit sorted(ns.natsorted(d), key=str.isdigit, reverse=True)
1 loop, best of 3: 9.77 s per loop

In [17]: %timeit ns.natsorted(d, key=lambda x: (not x.isdigit(), x))
1 loop, best of 3: 23.8 s per loop