我有一个python列表,其中响应的顺序很重要。我想过滤掉masterWKB.masterWKS.Cells(lastLineWKB, 1).PasteSpecial
值,只要它们出现在列表的末尾。我想知道是否有一种高效的方式可以从以下列表中找到:
nan
到没有任何尾随nan = float("nan")
responses = [1.0, nan, 9.0, nan, nan, nan, nan, nan, nan, nan, nan]
值的列表:
nan
我知道如何使用列表解析过滤掉所有[1.0, nan, 9.0]
值:
nan
但是不能想到一种直接的方法来在最后过滤掉import pandas as pd
[r for r in responses if pd.notnull(r)]
>>> [1.0, 9.0]
值而不将所有内容都转换为字符串并使用正则表达式。我可以做到这一点,但我担心性能,这是一个问题,因为它将执行数十万次。
答案 0 :(得分:2)
while responses and math.isnan(responses[-1]):
responses.pop()
更新:这并不像直线切片一样快。
>>> timeit.timeit('responses = list(r)\nwhile responses and isnan(responses[-1]): responses.pop()', 'from math import isnan; nan = float("nan"); r = [1.0, nan, 9.0, nan, nan, nan, nan, nan, nan, nan, nan]')
1.3209394318982959
>>> timeit.timeit('responses = list(r)\nresponses = responses[:3]', 'from math import isnan; nan = float("nan"); r = [1.0, nan, 9.0, nan, nan, nan, nan, nan, nan, nan, nan]')
0.29652016144245863
答案 1 :(得分:1)
没有内置函数或方法。但你可以使用一个循环:
while responses and math.isnan(responses[-1]):
del responses[-1]
正如你自己所看到的,这是以线性时间运行的,不会占用额外的空间。
答案 2 :(得分:0)
您可以撤消它并使用itertools.dropwhile
。这应该适用于任何价值。
r = [1.0, nan, 9.0, nan, nan, nan, nan, nan, nan, nan, nan]
list(itertools.dropwhile(lambda x: x == r[-1], reversed(r)))[::-1] + r[-1:]
要仅过滤nan
,您可以将lambda x: x == r[-1]
替换为math.isnan
:
list(itertools.dropwhile(math.isnan, reversed(r)))[::-1]
答案 3 :(得分:0)
我要做的是迭代列表一次,然后找到nans
的结束序列开始的位置。像
responses = [1.0, 'nan', 9.0, 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan']
first_index = -1
for i, val in enumerate(responses):
if val == 'nan':
if first_index == -1:
first_index = i
else:
first_index = -1
responses = responses[:first_index] # [1.0, 'nan', 9.0]
然后您可以执行单个切片操作。它比其他解决方案更冗长,但应该更快。
时间复杂性
根据to this page,切片操作为O(n),并且在列表上迭代为O(n),使得整个算法O(n)复杂。
更好的方法是向后迭代列表。