使用列表理解最佳表达式删除前导零的问题
Posted
技术标签:
【中文标题】使用列表理解最佳表达式删除前导零的问题【英文标题】:Problem removing leading zeros using a list comprehension best expression 【发布时间】:2018-10-11 16:11:13 【问题描述】:result
是一个数字列表:
result = ['0','5','0','1']
我想删除前导零,使用以下表达式:
result = result[next((i for i, x in enumerate(result)
if x != 0), len(result)):] or [0]
我的问题有两个:
1.) 我不理解这个表达方式 2.) 表达式本身不起作用:它不会删除任何零(前导或其他)
我希望列表推导能够删除每个零,而不仅仅是前导的。 我也对 len(result)): 表达式的一部分在做什么感到困惑?
【问题讨论】:
next
的第二个参数是可迭代对象耗尽时的默认值。从外观上看,这应该是找到第一个 0 的索引(如果存在),并相应地对列表进行切片。
这不起作用,因为您的项目是字符串,并且条件检查和整数。将其更改为result[next((i for i, x in enumerate(result) if x != '0'), len(result)):] or ['0']
,它应该可以工作。
你在哪里找到这个代码?
【参考方案1】:
表达式在列表中查找第一个非零值,返回剩余的列表。底部有更多细节。
分析
但是,您有字符:您的列表中没有整数 0
。因此,表达式仅返回原始列表。
解决方案
如果您希望它适用于字符,只需包含所需的引号即可:
result[next((i for i, x in enumerate(result) if x != '0'), len(result)):] or ['0']
这给你:
原码:
>>> result = ['0','5','0','1']
>>> result[next((i for i, x in enumerate(result) if x != 0), len(result)):] or [0]
['0', '5', '0', '1']
适应字符串/字符:
>>> result[next((i for i, x in enumerate(result) if x != '0'), len(result)):] or ['0']
['5', '0', '1']
>>> result = ['0','0','5','0','1']
>>> result[next((i for i, x in enumerate(result) if x != '0'), len(result)):] or ['0']
['5', '0', '1']
>>> result = ['7', '0','0','5','0','1']
>>> result[next((i for i, x in enumerate(result) if x != '0'), len(result)):] or ['0']
['7', '0', '0', '5', '0', '1']
表达逻辑
关键从句位于理解的最深处:
(i for
i, x in enumerate(result)
if x != '0')
在enumerate
子句中,i, x
遍历列表索引及其内容:(0, '0')
、(1, '5')
等。
if
检查零个字符;它过滤掉所有零。在内部子句找到非零值之前,i for
部分不会获得任何 i
值。
在那个点,外部next
运算符接管:它采用非零的第一个索引并将其返回给切片运算符(注意末尾的冒号),这返回列表的其余部分。
正如pault
已经提到的,末尾的len
是默认值:如果您的零过滤器取消了整个列表的资格(全为零),那么理解将len(result)
返回到next
。这意味着 next
将返回列表长度,而您的 result
切片返回一个空列表。 现在你的 or 表达式在第一个操作数中有一个“Falsy”值;它返回第二个操作数,列表['0']
。
【讨论】:
【参考方案2】:这是你用过的!
>>> result = ['0','5','0','1']
>>> result[next((i for i, x in enumerate(result) if x != 0), len(result)):] or [0]
['0', '5', '0', '1']
让我们分解你的列表理解!
[i for i,x in enumarate(result)]
将enumerate(result)
解包为 i 和 x。也就是说,
>>> enumerate(result)
<enumerate object at 0x7fc81d12bdc0>
>>> list(enumerate(result))
[(0, '0'), (1, '5'), (2, '0'), (3, '1')]
>>> for i,x in enumerate(result):
... print i,x
...
0 0
1 5
2 0
3 1
用非零值过滤结果,
>>> [i for i, x in enumerate(result) if x != 0]
[0, 1, 2, 3]
现在看看用x
比较字符串和整数的区别
>>> [i for i, x in enumerate(result) if x != '0'] #list comprehension
[1, 3]
>>> len(result)
4
下一个(迭代器[,默认])
从迭代器返回下一项。如果给出默认值并且迭代器 用尽,它被返回而不是引发 StopIteration。
也就是说,
>>> next([i for i, x in enumerate(result) if x != 0], len(result)) # next takes first argument as iterator, in this example we've given a list, so exception is raised
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator
>>> next((i for i, x in enumerate(result) if x != '0'), len(result)) #comparing with string '0'
1
现在,我们得到了列表中第一个具有非零值的索引(我们将其设为 nzindex)。
有了这个索引,我们就用string slicing 来获取结果之后的所有元素[nzindex:]
这将返回索引之后直到结束的所有元素。
>>> result[next((i for i, x in enumerate(result) if x != '0'), len(result)):]
['5', '0', '1']
如果字符串切片返回空列表(falsey结果),则返回默认值result[0]!
>>> result = ['0']
>>> result[next((i for i, x in enumerate(result) if x != '0'), len(result)):] or result[0]
['0']
话虽如此,如果您想删除列表中的所有零,
>>> result = ['0','5','0','1']
>>> [x for i,x in enumerate(result) if x!='0']
['5', '1']
如果您想只删除前导零,一种更有效的方法是,
>>> next(i for i,x in enumerate(result) if x!='0')
1
>>> result[next(i for i,x in enumerate(result) if x!='0'):]
['5', '0', '1']
【讨论】:
以上是关于使用列表理解最佳表达式删除前导零的问题的主要内容,如果未能解决你的问题,请参考以下文章