Python 中如何刪除一個列表 List 中多個符合條件的元素?
假設有一個列表:
a = [1, 1, 0, 2, 0, 0, 8, 3, 0, 2, 5, 0, 2, 6]
判斷如果a列表中元素"2"前面的一個元素是"0",那麼刪除這個元素"0",請問該如何操作?
[x[0] for x in zip(a,a[1:]+[None]) if x!=(0,2)]又:注意其他答案有些不能處理len(a) in [0,1]的情形
典型的reduce問題…
from functools import reduce
a = [1, 1, 0, 2, 0, 0, 8, 3, 0, 2, 5, 0, 2, 6]
def reducer(acc, y):
if acc and acc[-1] == 0 and y == 2:
acc.pop()
acc.append(y)
return acc
result = reduce(reducer, a, [])
assert result == [1, 1, 2, 0, 0, 8, 3, 2, 5, 2, 6]
這個方案,2前面如果有多個0,只會刪除1個0(比較符合題主的意思)。但是如果需要刪除多個0,就需要pop多次了:
from functools import reduce
a = [1, 1, 0, 2, 0, 0, 8, 3, 0, 2, 5, 0, 0, 2, 6]
def reducer(acc, y):
if y == 2:
while acc and acc[-1] == 0:
acc.pop()
acc.append(y)
return acc
result = reduce(reducer, a, [])
assert result == [1, 1, 2, 0, 0, 8, 3, 2, 5, 2, 6]
def foo(a):
n = 0
for e in a:
if e == 0:
n += 1
elif e == 2:
n = 0
yield 2
else:
for i in range(n): yield 0
n = 0
yield e
for i in range(n): yield 0
print(list(foo([0]))) # 0
print(list(foo([1]))) # 1
print(list(foo([0, 1]))) # 0 1
print(list(foo([0, 2]))) # 2
print(list(foo([0, 2, 0]))) # 2 0
print(list(foo([0, 0, 2, 0]))) # 2 0
print(list(foo([0, 0, 0, 2, 0]))) # 2 0
print(list(foo([1, 0, 0, 0, 2, 0]))) # 1 2 0
print(list(foo([1, 0, 0, 0, 2, 0, 2]))) # 1 2 2
這種問題還要什麼fp,要什麼遞歸……
python中個人感覺filter函數是正解。畢竟有函數不用卻自己寫循環不符合寫程序懶惰的特質
比如list中去空字元(配合lambda表達式):
condition = lambda t: t != "" (判斷符合條件很複雜就不能使用lambda,自己寫方法吧)
filter_list = list(filter(condition, list)
a = [1, 1, 0, 2, 0, 0, 8, 3, 0, 2, 5, 0, 2, 6]
for i in range(0,len(a)-2):
if(a[i]==0 and a[i+1]==2):
del(a[i])
i=i-1
a
[1, 1, 2, 0, 0, 8, 3, 2, 5, 2, 6]
想了很多方法,終於找到一個感覺比較好的
a = [1, 2, 1, 0, 2, 0, 0, 8, 3, 0, 2, 5, 0, 2, 6, 1, 2]
可以找出每個符合條件的"0"的索引值i,但是如果直接用del[i]刪除此元素,會導致列表的索引值發生改變,按照原來的索引值刪除就會出錯,比較好的做法是:
to_delete = []
for i,item in enumerate(a):
if item == 2:
if a[i-1] == 0:
to_delete.append(i-1)
a_new = [item for i,item in enumerate(a) if i not in to_delete]
[1, 2, 1, 2, 0, 0, 8, 3, 2, 5, 2, 6, 1, 2]
for i in range(len(a)-1,-1,-1):
if a[i]==0 and a[i+1]==2:
a.pop(i)
參考了python幫助文檔里去除list中重複字元的代碼。我也是剛學習python,剛起步,看到了忍不住聯繫一下。
l = [l[i] for i in filter(lambda i: l[i] !=0 or i == len(l) or l[i+1] != 2, range(len(l)))]
如果真的是你這樣的數據…變字元串join起來把所有的02變成2不就好了?
底下六種方式都可以解:a= [0,2,0,0,200,0,20,22,0,2,222,0,0,20,0,0,0,2,0,2]的問題
如果認真想的話應該還有許多方式,有興趣的人可以嘗試。
——————————————————————————
第一種方式:
y=[a.pop(i) for i in range(len(a)) if a[i:i+2]==[0,2]]
print(a)——————————————————————————
第二種方式:
如果a的長度是單數 需要在a的後面+[0] 然後 print(eval(y)[:-1])
z=iter(a)
y=re.sub("[()]","",str([(x,next(z)) for x in z]).replace("(0, 2)","2"))
print(eval(y))——————————————————————————
第三種方式:
for i in range(len(a)):
try: if str(a[i])+str(a[i+1])=="02": del a[i] except Exception as e: breakprint(a)
——————————————————————————
第四種方式:
————————————————————————————————————
第五種方式:
y=iter(a+[0])
print(next(y))b=list(filter(lambda x:x+(next(y)/100)!=0.02,a))print(b)
—————————————————————————————————————
第六種方式:
#如果a長度是雙數
k=[]
for x,y in zip(a[::2],a[1::2]):
if [x,y] == [0, 2]: k.extend([y]) else: k.extend([x,y])print(k)
#如果a長度是單數a+=[0]k=[]
for x,y in zip(a[::2],a[1::2]): if [x,y] == [0, 2]: k.extend([y]) else: k.extend([x,y])print(k[:-1])
——————————————————————————————————
我先聲明我也是剛學習Python的,這個問題我獻醜一下吧。功能應該能實現,但是如果考慮代碼簡潔程度或者效率,還是坐等更高明的答案了。
def remove_1(lst):
ans = []
for i in range(len(lst)):
if lst[i] == 0:
try:
if lst[i+1] == 2: pass
else: ans.append(lst[i])
except: ans.append(lst[i])
else: ans.append(lst[i])
return ans
# 刪除列表中連續重複項,for遍歷會出錯,解決方法就是把需要的數據放到新的列表中
# 方法1 放在空的列表中list1 = [1, 1, 2, 2, 3, 4, 17, 17, 23, 45, 23, 23, 13, 13, 36]list2 = []for i in list1:
if i &> 18:list2.append(i)print(list2)# 利用列表表達式生成新的列表
list1 = [1, 1, 2, 2, 3, 4, 17, 17, 23, 45, 23, 23, 13, 13, 36]
list3 = [i for i in list1 if i &> 18]print(list3)# 方法3:利用filter和lambda函數生成新的列表
list1 = [1, 1, 2, 2, 3, 4, 17, 17, 23, 45, 23, 23, 13, 13, 36]list4 = list(filter(lambda x : x &> 18, list1))print(list4)print
(lambda l:
(lambda f, l: f(f, l))
(lambda f, l: l and l[0:1] if len(l) &< 2 else (f(f, l[1:]) if l[0] == 0 and l[1] == 2 else l[0:1] + f(f, l[1:])), l)
)(a)
用filter函數
[a[i] for i in range(len(a)) if a[i]!= 0 or i+1==len(a) or a[i+1] != 2]
唉。。。我很無聊啊。。。樓上就沒有一個對的。。。就算拿著list comprehension來搗鼓,或者拿著接近FP的lambda來搗鼓了也得先把題目搞清楚啊。。。那位用lambda的,也至少得再加上一個不動點子嘛~,
==== 你們的錯在於如果遇到a = [1, 1, 0, 2, 0, 0, 8, 3, 0, 2, 5, 0, 0, 2, 6]
你們的output就是:
[1, 1, 2, 0, 0, 8, 3, 2, 5, 0, 2, 6]
這個結果顯然不對啊,所以說,引入iteration很重要。
--------最近順手就寫個lisp版本吧。。。反正改過去就是個遞歸而已沒差別了(define (match-pattern list)
(cond ((null? list) 0)
((and (eq? 0 (car list)) (eq? 2 (cadr list))) (+ 1 (match-pattern (cdr list))))
(else (+ 0 (match-pattern (cdr list))))))
(define (delete-pattern list)
(define (delete list)
(cond ((null? list) "())
((and (eq? 0 (car list)) (eq? 2 (cadr list))) (cons 2 (delete (cddr list))))
(else (cons (car list) (delete (cdr list))))))
(define (iter-delete list)
(if (= 0 (match-pattern list))
list
(iter-delete (delete list))))
(iter-delete list))
Output:
(define b (list 1 1 0 2 0 0 8 3 0 2 5 0 0 2 6))
(delete-pattern b)
;=&> (1 1 2 0 0 8 3 2 5 2 6)
(define a (list 1 1 0 2 0 0 8 3 0 2 5 0 2 6))
(delete-pattern a)
;=&> (1 1 2 0 0 8 3 2 5 2 6)
一般不建議在原列表上面直接操作,最好是新生成一個列表
&>&>&> a = [1, 1, 0, 2, 0, 0, 8, 3, 0, 2, 5, 0, 2, 6]
&>&>&> b = [a[i] for i in range(0, len(a) - 1) if not ( a[i] == 0 and a[i+1] == 2 )]
&>&>&> b.append(a[-1])
[1, 1, 2, 0, 0, 8, 3, 2, 5, 2, 6]
用filter配合lambda表達式豈不是美滋滋?
a=[a[i] for i in range(len(a)) if not(a[i]==0 and a[i+1]==2)]
做一個判斷來看產生新列表裡面是否還存在符合條件的元素,如果有則要繼續刪除,參考了樓上匿名用戶的代碼PS:我剛開始學python,這個程序其實效率很低下,有沒有更高效一點的,求指導~
a=3,2,1,6,5,0,2,1,3,5,0,2,1,2,0,0,0,2,3,6,5,2,2
while(filter(lambda i:a[i]==0 and a[i+1]==2,range(len(a)-1))):
a=[a[i] for i in filter(lambda i:a[i]!=0 or i==len(a) or a[i+1]!=2,range(len(a)))]
推薦閱讀:
※被代碼佔領的世界會是什麼樣?
※怎樣用 Matlab 寫出優雅的代碼?
※opencv庫的python版為啥比c++版小這麼多?是功能有區別嗎?
※如何用 Python 中的 NLTK 對中文進行分析和處理?
※用python去搞數學建模可行性大不大?
TAG:Python |