2015-02-10 139 views
3

我有一個列表TrueFalse,它被認爲是循環的(第一個元素在最後一個之後)。找到最接近的True元素的索引,之前的哪個元素具有給定的索引?查找循環列表中的上一個匹配元素

這是我的解決方案。這是非常簡單的,但不是很Python的,因爲我認爲:

def prev_element(a, i): 
    i -= 1 
    while not a[i]: 
     i -= 1 
    return i % len(a) 

這將提高IndexError的情況下,不存在這樣的元素,這是確定我。我利用這樣一個事實,即一個列表可能會被索引爲負索引,這會導致列表循環。有更好的解決方案一些很酷的單線,也許?

+2

我認爲你的解決方案非常好!出於教條的原因,不需要聰明,不僅僅是您的解決方案「應該」使用訪問者模式或抽象基類。 – Cuadue 2015-02-10 22:32:21

+1

它起作用,它簡短而又甜美,簡單易讀 - 什麼是非pythonic? – wwii 2015-02-10 22:59:03

+0

@Cuadue我是python的新手,這就是爲什麼我認爲可能有一些奇特的功能或者我甚至不知道的方法。現在,當我看到答案時,我確信我的解決方案至少不會比其他問題更糟糕。 – Mikhail 2015-02-11 07:59:34

回答

1

我會做這個

def prev_element(seq, idx): 
    for new_idx,el in enumerate(reversed(seq[:idx])): 
     if el == True: 
      return idx - new_idx 

另一種選擇是:

def prev_element(seq, idx): 
    max(i for i,el in enumerate(seq[:idx]) if el==True) 

甚至:

def prev_element(seq, idx): 
    min([i for i,el in enumerate(seq) if el==True], key=lambda i: abs(idx-i)) 
+0

另一個選項不循環,第三個鍵不是函數 – JuniorCompressor 2015-02-10 21:25:03

+0

@JuniorCompressor我不確定他的數據結構是否正在處理循環或者如果我們正在編碼。 – 2015-02-10 21:28:37

2
from itertools import count 

def prev_element(a, i): 
    cyc = count(i - 1, -1) 
    res = next((next(cyc) + 1 for _ in range(len(a)) if a[next(cyc)]), None) 
    return res % len(a) if res else res 

/您可以使用最多用一試,除了使用一個lambda獲得最大值,在它不能的約束下小於我們正在搜索的指數,如果我們沒有指數下面它會得到上述指數。

def prev_element(a, ind): 
    try: 
     return max((i for i, ele in enumerate(a) if ele and i != ind), key=lambda x: (x < ind, x)) 
    except ValueError: 
     return None 

沒有一個try /除了使用列表:

def prev_element(a, ind): 
    inds = [i for i, ele in enumerate(a) if ele and i != ind] 
    return max(inds,key=lambda x: (x < ind, x)) if inds else None 
+0

您的答案不會循環 – JuniorCompressor 2015-02-10 21:25:53

+0

這不起作用。 – Mikhail 2015-02-10 22:07:52

+0

@Mikhail,它現在不會拋出indexError – 2015-02-10 22:09:24

2

JuniorCompressor's answer,最簡單的&愚蠢(R)的方法的改進:

next(i%len(a) for i in range(n-1,n-len(a)-1,-1) if a[i]) 

其中n是該指數的初始值。

相關問題