4

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

目前,此代码确实在序列结束后立即返回列表项,但是我对拥有这么多嵌套的 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]

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

4

3 回答 3

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

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

于 2013-07-19T08:55:20.403 回答
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在某个时候引发 an ,因为您访问list[i+1]where imay be len(list) - 1。上面的代码不会产生任何错误,因为切片可能会产生比索引差短的切片,这意味着seq[j:j+3]可以有少于 3 个元素。如果这是一个问题,您应该调整您正在迭代的索引。

最后一点:不要使用该名称list,因为它会隐藏内置名称。

于 2013-07-19T08:43:23.287 回答
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]]

当然有更有效的方法来做到这一点,但这是简单、简短和 python 风格的。

于 2013-07-19T08:59:20.217 回答