在循环列表中查找上一个匹配元素

时间:2015-02-10 20:45:47

标签: python

我有一个TrueFalse的列表,它被认为是循环的(第一个元素位于最后一个元素之后)。找到最接近True元素的索引的更好方法是什么,元素之前具有给定索引?

这是我的解决方案。我认为它非常简单,但不是非常pythonic:

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

如果没有这样的元素,这将引发IndexError,这对我来说没问题。我利用了一个事实,即列表可以用负索引编制索引,这使得列表循环。更好的解决方案?一些很酷的单行,也许?

3 个答案:

答案 0 :(得分:3)

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

你可以使用max with try / except使用lambda获取max,在约束条件下它不能小于我们搜索的索引,如果我们没有下面的索引,它将获得上面的索引。< / p>

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

没有尝试/除了使用列表:

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

答案 1 :(得分: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))

答案 2 :(得分:1)

JuniorCompressor's answer的改进,这是最简单和最愚蠢的方法:

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

其中n是初始值的索引。