Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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_List_Nan - Fatal编程技术网

Python:仅当在列表末尾时才删除重复的值

Python:仅当在列表末尾时才删除重复的值,python,list,nan,Python,List,Nan,我有一个python列表,其中响应的顺序很重要。我只想过滤掉列表末尾出现的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

我有一个python列表,其中响应的顺序很重要。我只想过滤掉列表末尾出现的
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]

但是,如果不将所有内容转换为字符串并使用正则表达式,就想不出一种直接的方法在最后过滤掉
nan
值。我可以这样做,但我担心性能,这是一个问题,因为它将执行数十万次。

没有内置函数或方法。但您可以使用循环:

while responses and math.isnan(responses[-1]):
    del responses[-1]
正如您自己所见,这在线性时间内运行,并且不使用额外的空间

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

您可以将其反转并使用
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]

我要做的是在列表上迭代一次,然后找到
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]
然后可以执行单个切片操作。它比其他解决方案更详细,但应该更快

时间复杂性

因此,切片操作是O(n),对列表的迭代是O(n),这使得整个算法的复杂性是O(n)


更好的方法是向后迭代列表。

>它将执行数十万次。使用
responses=responses[:3]
您将创建一个新列表。尝试计时
responses[:]=responses[:3]
delresponses[3://code>(仍然要记住,只有当
responses
是一个大列表时,计时的差异才是相关的)顺便说一句,要小心:通过使用
timeit()
setup
参数初始化列表,您只初始化了一次。也就是说,
timeit()
将运行您的代码10000次,但列表只会修改一次。@AaronDuke正确更新以处理Andrea的评论,单个片段的速度要快得多。这个答案不是最优的。很难想出一个不是O(n)的解决方案。这个的实际表现是什么?你能用
timeit
检查一下吗?