gpt4 book ai didi

Python 将列表拆分为开始和结束关键字模式的子列表

转载 作者:太空狗 更新时间:2023-10-29 18:19:46 25 4
gpt4 key购买 nike

如果我有一个列表,请说:

lst = ['foo', 'bar', '!test', 'hello', 'world!', 'word']

使用 ! 字符,我将如何返回给定的列表:

lst = ['foo', 'bar', ['test', 'hello', 'world'], 'word']

我在为此找到解决方案时遇到了一些困难。这是我尝试过的一种方法:

def define(lst):
for index, item in enumerate(lst):
if item[0] == '!' and lst[index+2][-1] == '!':
temp = lst[index:index+3]
del lst[index+1:index+2]
lst[index] = temp
return lst

如有任何帮助,我们将不胜感激。

最佳答案

假设没有以 ! 开头和结尾的元素,例如 '!foo!'

首先我们可以编写辅助谓词

def is_starting_element(element):
return element.startswith('!')


def is_ending_element(element):
return element.endswith('!')

然后我们可以写 generator-function(因为它们很棒)

def walk(elements):
elements = iter(elements) # making iterator from passed iterable
for position, element in enumerate(elements):
if is_starting_element(element):
yield [element[1:], *walk(elements)]
elif is_ending_element(element):
yield element[:-1]
return
else:
yield element

测试:

>>> lst = ['foo', 'bar', '!test', 'hello', 'world!', 'word']
>>> list(walk(lst))
['foo', 'bar', ['test', 'hello', 'world'], 'word']
>>> lst = ['foo', 'bar', '!test', '!hello', 'world!', 'word!']
>>> list(walk(lst))
['foo', 'bar', ['test', ['hello', 'world'], 'word']]
>>> lst = ['hello!', 'world!']
>>> list(walk(lst))
['hello']

正如我们从上一个示例中看到的那样,如果关闭元素多于打开元素,则剩余的关闭元素将被忽略(这是因为我们正在从生成器中返回)。因此,如果 lst 具有无效签名(开始元素和结束元素之间的差异不等于零),那么我们可能会有一些不可预测的行为。作为摆脱这种情况的一种方法,我们可以在处理之前验证给定的数据,如果数据无效则引发错误。

我们可以这样写验证器

def validate_elements(elements):
def get_sign(element):
if is_starting_element(element):
return 1
elif is_ending_element(element):
return -1
else:
return 0

signature = sum(map(get_sign, elements))
are_elements_valid = signature == 0
if not are_elements_valid:
error_message = 'Data is invalid: '
if signature > 0:
error_message += ('there are more opening elements '
'than closing ones.')
else:
error_message += ('there are more closing elements '
'than opening ones.')
raise ValueError(error_message)

测试

>>> lst = ['!hello', 'world!']
>>> validate_elements(lst) # no exception raised, data is valid
>>> lst = ['!hello', '!world']
>>> validate_elements(lst)
...
ValueError: Data is invalid: there are more opening elements than closing ones.
>>> lst = ['hello!', 'world!']
>>> validate_elements(lst)
...
ValueError: Data is invalid: there are more closing elements than opening ones.

最后我们可以编写带有验证的函数

def to_sublists(elements):
validate_elements(elements)
return list(walk(elements))

测试

>>> lst = ['foo', 'bar', '!test', 'hello', 'world!', 'word']
>>> to_sublists(lst)
['foo', 'bar', ['test', 'hello', 'world'], 'word']
>>> lst = ['foo', 'bar', '!test', '!hello', 'world!', 'word!']
>>> to_sublists(lst)
['foo', 'bar', ['test', ['hello', 'world'], 'word']]
>>> lst = ['hello!', 'world!']
>>> to_sublists(lst)
...
ValueError: Data is invalid: there are more closing elements than opening ones.

编辑

如果我们想处理以 ! 开头和结尾的元素,例如 '!bar!',我们可以使用 itertools.chain 修改 walk 函数,例如

from itertools import chain


def walk(elements):
elements = iter(elements)
for position, element in enumerate(elements):
if is_starting_element(element):
yield list(walk(chain([element[1:]], elements)))
elif is_ending_element(element):
element = element[:-1]
yield element
return
else:
yield element

我们还需要通过修改get_sign函数来完成验证

def get_sign(element):
if is_starting_element(element):
if is_ending_element(element):
return 0
return 1
if is_ending_element(element):
return -1
return 0

测试

>>> lst = ['foo', 'bar', '!test', '!baz!', 'hello', 'world!', 'word']
>>> to_sublists(lst)
['foo', 'bar', ['test', ['baz'], 'hello', 'world'], 'word']

关于Python 将列表拆分为开始和结束关键字模式的子列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49596604/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com