以更Pythonic的方式重写嵌套的if语句

时间:2013-07-19 08:34:19

标签: python list if-statement nested pattern-matching

我正在研究一个函数,给定一个序列,尝试在列表中找到所述序列,然后应该在该序列终止后立即返回列表项。

目前这段代码确实在序列结束后立即返回列表项,但是我不满足于拥有这么多嵌套的if语句并且很想重写它但是我不知道该如何去关于它,因为它与我过去写过的任何东西完全不同,并且感觉有点不合时宜。

def sequence_in_list(seq, lst):
    m, n = len(lst), len(seq)
    for i in xrange(m):
        for j in xrange(n):
            if lst[i] == seq[j]:
                if lst[i+1] == seq[j+1]:
                    if lst[i+2] == seq[j+2]:
                        return lst[i+3]

(我的意图是扩展这个函数,以便如果该序列在整个列表中出现不止一次,它应该返回序列后最常发生的后续项目)

3 个答案:

答案 0 :(得分:2)

我会用发生器切片:

sequence = [1, 2, 3, 5, 1, 2, 3, 6, 1, 2, 3]
pattern = [1, 2, 3]

def find_item_after_pattern(sequence, pattern):
    n = len(pattern)

    for index in range(0, len(sequence) - n):
        if pattern == sequence[index:index + n]:
            yield sequence[index + n]

for item in find_item_after_pattern(sequence, pattern):
    print(item)

你会得到:

5
6

该功能效率不高,不适用于无限序列,但它简短且通用。

答案 1 :(得分:1)

由于您要比较连续索引,并假设lstseq属于同一类型,您可以使用切片:

def sequence_in_list(seq, lst):
    m, n = len(lst), len(seq)
    for i in xrange(m):
        for j in xrange(n):
            if lst[i:i+3] == seq[j:j+3]:
                return lst[i+3]

如果序列属于不同类型,则应在进行比较之前转换为通用类型(例如,如果lst[i:i+3] == list(seq[j:j+3])是字符串且seq是列表,则lst将起作用)。

或者,如果序列不支持切片,您可以使用内置的all检查更多条件:

def sequence_in_list(seq, lst):
    m, n = len(lst), len(seq)
    for i in xrange(m):
        for j in xrange(n):
            if all(lst[i+k] == seq[j+k] for k in range(3)):
                return lst[i+3]

如果您想将检查扩展到10个而不是3个,只需将range(3)更改为range(10)

附注:您的原始代码会在某个时刻引发IndexError,因为您访问的list[i+1] i可能是len(list) - 1。上面的代码不会产生任何错误,因为切片可能会产生比索引差异更短的切片,seq[j:j+3]可能少于3个元素。如果这是一个问题,您应该调整迭代的索引。

上次评论:请勿使用名称list,因为它会隐藏内置名称。

答案 2 :(得分:0)

您可以将列表理解与切片结合起来,使比较更具可读性:

n, m = len(lst), len(seq)
[lst[j+3] for i in range(m-2) for j in range(n-2) if seq[i:i+3] == lst[j:j+3]]

当然有更有效的方法,但这很简单,简短,蟒蛇风格。