python - 在列表中查找邻居

标签 python list

我有一个列表:

l=['a','>>','b','>>','d','e','f','g','>>','i','>>','>>','j','k','l','>>','>>']

我需要提取 '>>' 的所有邻居并将它们分成组,其中它们之间的元素既不是 '>>' 也不是 '>>' 的邻居'>>'

对于示例列表,预期结果将是:

[['a', 'b', 'd'], ['g', 'i', 'j'], ['l']]

我已经尝试了很多东西,但是所有简单的东西都以某种方式失败了。目前似乎唯一有效的代码是这样的:

def func(L,N):
    outer=[]
    inner=[]
    for i,e in enumerate(L):
        if e!=N:
            try:
                if L[i-1]==N or L[i+1]==N:
                    inner.append(e)
                elif len(inner)>0:
                    outer.append(inner)
                    inner=[] 
            except IndexError:
                pass
    if len(inner):
        outer.append(inner)
    return outer

func(l,'>>')

Out[196]:
[['a', 'b', 'd'], ['g', 'i', 'j'], ['l']]

虽然看起来可行,但我想知道是否有更好、更清洁的方法来做到这一点?

最佳答案

我认为最 pythonic 和易于阅读的解决方案应该是这样的:

import itertools

def neighbours(items, fill=None):
    """Yeild the elements with their neighbours as (before, element, after).

    neighbours([1, 2, 3]) --> (None, 1, 2), (1, 2, 3), (2, 3, None)

    """
    before = itertools.chain([fill], items)
    after = itertools.chain(items, [fill]) #You could use itertools.zip_longest() later instead.
    next(after)
    return zip(before, items, after)

def split_not_neighbour(seq, mark):
    """Split the sequence on each item where the item is not the mark, or next
    to the mark.

    split_not_neighbour([1, 0, 2, 3, 4, 5, 0], 0) --> (1, 2), (5)

    """
    output = []
    for items in neighbours(seq):
        if mark in items:
            _, item, _ = items
            if item != mark:
                output.append(item)
        else:
            if output:
                yield output
                output = []
    if output:
        yield output

我们可以这样使用:

>>> l = ['a', '>>', 'b', '>>', 'd', 'e', 'f', 'g', '>>', 'i', '>>', '>>',
...      'j', 'k', 'l', '>>', '>>']
>>> print(list(split_not_neighbour(l, ">>")))
[['a', 'b', 'd'], ['g', 'i', 'j'], ['l']]

注意巧妙地避免任何直接索引。

编辑:一个更优雅的版本。

def split_not_neighbour(seq, mark):
    """Split the sequence on each item where the item is not the mark, or next
    to the mark.

    split_not_neighbour([1, 0, 2, 3, 4, 5, 0], 0) --> (1, 2), (5)

    """
    neighboured = neighbours(seq)
    for _, items in itertools.groupby(neighboured, key=lambda x: mark not in x):
        yield [item for _, item, _ in items if item != mark]

关于python - 在列表中查找邻居,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13129281/

相关文章:

python - 在 macOS 上的 VS Code 中启动 Python 脚本时出现 `SyntaxError: invalid syntax`

Python将numpy数组插入sqlite3数据库

list - 努力从列表中取出最后一个元素(Haskell)

python - 将两个字典的信息翻译成字典列表

Python:对休眠线程的惩罚

python - Django-Simple-Captcha 添加CSS

python - BeautifulSoup:只要进入一个标签,不管有多少封闭标签

python - -Python- 基于格式的排序列表

c# - List.OrderBy 定义变量中的顺序

list - OCaml:删除列表的第一个元素