简体   繁体   中英

Find previous matching element in a cyclic list

I have a list of True and False , which is considered cyclic (first element comes after the last one). What is the better way to find index of the closest True element, preceding an element with the given index?

Here is my solution. It is very straightforward, but not very pythonic, as I think:

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

This will raise IndexError in case there is no such element, which is ok for me. I exploit the fact that a list may be indexed with negative indices, which makes the list cycling. Any better solutions? Some cool one-liner, maybe?

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

You can use max with a try/except using a lambda to get the max, under the constraint that it cannot be less than the index we are searching from, if we have no index below it will get the index above.

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

Without a try/except use a list:

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

I would do this

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

The other option is:

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

Or even:

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

An improvement over JuniorCompressor's answer , the most simple&stupid(r) approach:

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

where n is the index of the initial value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM