我有一个类似Python列表的结构,有超过100万个元素。每个元素都采用三个可能值中的一个,即-1
,0
或1
。我想要实现的是用下一个非零值替换所有零。
例如,如果我有
[1, 0, 0, -1, 0, 1, 0, 0, 0, -1]
手术后我会
[1, -1 , -1 ,-1, 1 ,1, -1 , -1 , -1 , - 1]。
我可以有一个嵌套的循环结构来实现这个目标,但是在列表中有超过100万个元素,它需要永远运行。有谁知道一个更快的算法来实现这个目标?
答案 0 :(得分:4)
您可以先尝试创建Series
,然后replace
0
至NaN
,最后使用fillna
:
import pandas as pd
import numpy as np
li = [1, 0, 0, -1, 0, 1, 0, 0, 0, -1]
s = pd.Series(li)
print s
0 1
1 0
2 0
3 -1
4 0
5 1
6 0
7 0
8 0
9 -1
dtype: int64
print s.replace({0:np.nan})
0 1
1 NaN
2 NaN
3 -1
4 NaN
5 1
6 NaN
7 NaN
8 NaN
9 -1
dtype: float64
print s.replace({0:np.nan}).fillna(method='bfill')
0 1
1 -1
2 -1
3 -1
4 1
5 1
6 -1
7 -1
8 -1
9 -1
dtype: float64
或者replace
使用loc
,然后按astype
转换为int,最后使用tolist
:
s.loc[s == 0] = np.nan
s.loc[s == 0] = np.nan
print s.fillna(method='bfill').astype(int).tolist()
[1, -1, -1, -1, 1, 1, -1, -1, -1, -1]
答案 1 :(得分:1)
这是一个纯Python解决方案。
创建一个保留先前值状态的小类,并将当前值与此先前值进行比较。
class Checker:
def _compare(self, val):
if val or not self.prior:
self.prior = val
return val
return self.prior
def reverse_fill_list(self, some_list):
self.prior = None
return [self._compare(v) for v in some_list[::-1]][::-1]
然后以相反的顺序在列表中使用列表推导(使用[:: - 1]反转)。然后再次反转结果以恢复原始订单。
some_list = [1, 0, 0, -1, 0, 1, 0, 0, 0, -1]
c = Checker() # Instantiate object.
>>> c.reverse_fill_list(some_list)
[1, -1, -1, -1, 1, 1, -1, -1, -1, -1]
np.random.seed(0)
# Create one million values in range [-1, 0, 1].
a = np.random.random_integers(-1, 1, 1000000)
>>> a[:10]
array([-1, 0, -1, 0, 0, 1, -1, 1, -1, -1])
%timeit c.reverse_fill_list(a)
1 loops, best of 3: 311 ms per loop
使用Pandas(使用@Jezrael解决方案)的结果更快。
>>> pd.Series(a).replace({0:np.nan}).fillna(method='bfill').tolist()
10 loops, best of 3: 136 ms per loop
答案 2 :(得分:0)
你可以从最后开始迭代。这将是 O ( n )解决方案。
a=[0,1,0,0,0,0,-1,0];
length=len(a);
length=length-1;
//Assuming if last value is 0 you just let it be and the 0s before it.
val=0;
print a
for i in range(length):
if (a[length-i] != 0):
val=a[length -i];
else:
a[length-i]=val;
i=i+1;
print a
exit();
答案 3 :(得分:0)
如果你想要纯Python,你可以使用一个简单的while
循环:
li=[1, 0, 0, -1, 0, 1, 0, 0, 0, -1]
i=len(li)-1
while i:
if li[i]:
val=li[i]
else:
li[i]=val
i-=1
>>> li
[1, -1, -1, -1, 1, 1, -1, -1, -1, -1]
假设最后一个值是1或-1,但你没有指定最终值可能会欺骗你......