2013-11-03 31 views
1

當我需要根據某些條件從清單的兩端刪除幾個元素時,遇到了一些問題。例如,假設我想從列表的兩端刪除元素,只要遇到第一個0(包括前0),就從位置q開始。基於條件的切割清單尾部

例子:

mylist = [1,1,0,1,0,1,2,3,1,5,1,3,1,0,2] 

應該變成:

[1,2,3,1,5,1,3,1] 

,如果我們採取q爲7。所以,我們去7元,開始去左邊,並用第一0遇到我們請記住索引i0並將其關閉mylist = mylist[i0+1:]。重複右側的相同步驟。

使用這個邏輯,我完成了兩個循環,完全如上所述。但似乎有點複雜。有沒有更簡單的方法來處理這樣的任務?

+1

它爲什麼複雜?任何答案都必須做相當於遍歷數值和檢查這些位置的零點。我沒有看到答案會如何改善你已有的代碼。 –

+0

@SimeonVisser大概是因爲以前的解決方案暗示需要兩個完整的迭代?我認爲懶惰地評估條件只有清單的相關部分是合理的改進,但絕對不是驚天動地。 –

+0

@SimeonVisser通過縮短代碼明智:) – sashkello

回答

2

個人,我會做專門的辦法是向後看的零隻需返回索引並適當調整即可返回到原始列表。我擔心可能沒有超清晰,所以讓我告訴你我是什麼意思代碼:

zero = lambda l: next(i for i,v in enumerate(l) if v==0) 
ending_zero = q + zero(mylist[q:]) 
starting_zero = q - zero(mylist[:q:-1]) 
return mylist[starting_zero:ending_zero] 

或者在一個函數進行包裝,並增加了一些一般要求(不一定只是等於零)

def two_directional_slice(original, condition, q): 
    condition = lambda l: (i for i,v in enumerate(l) if condition(v)).next() 
    ending_condition = q + condition(mylist[q:]) 
    starting_condition = q - condition(mylist[:q:-1]) 
    return mylist[starting_condition:ending_condition] 

因爲它懶惰地評估條件,我認爲你通常比使用迭代更好,但是在最壞的情況下,這隻會迭代你的列表一次。

只是要徹底,這裏是你將如何使用,去年實施的第一個問題:

return two_directional_slice(mylist, lambda x: x==0, 7) 
+0

將'(...)。next()'更改爲'next(...)',它也適用於Python 3。此外,你通過切分創建兩個新列表,所以我不認爲這個解決方案實際上會更快,除非你使用'itertools.islice'。 – Blender

0

就想出了這個:

[mylist[i] for i in range(len(mylist)) if i==q or (i < q and 0 not in mylist[i:q+1]) or (i > q and 0 not in mylist[q:i+1])] 

作品在我的情況下,但不是很普遍?

+0

絕對有效,但如果我看到有人將此代碼放入代碼庫,我正在管理我不會讓它通過代碼審查。 –

+0

它工作嗎?當我用'q = 7'運行它時,我得到了'[1,2,1,5,1,3,1,0]'。這不像給出的示例輸出。最後有一個'0'應該在那裏嗎? – iCodez

+0

@iCodez固定... – sashkello

1

下面是一個使用itertools.takewhile了一個非常有效,兩行的解決方案:

>>> mylist = [1,1,0,1,0,1,2,3,1,5,1,3,1,0,2] 
>>> q = 7 
>>> 
>>> from itertools import takewhile as tw 
>>> list(tw(bool, mylist[q::-1]))[::-1] + list(tw(bool, mylist[q+1:])) 
[1, 2, 3, 1, 5, 1, 3, 1] 
>>> 

這裏重要的是0評估爲False。這意味着您可以「拿」而數字不等於0