替换任何类型的对象列表的模式,类似于字符串的 .replace



使用字符串,您可以替换长度大于 1 的子字符串。例如,'abcabc'.replace('abca','*')产生'*bc'

我想用一个列表来做这件事。例如,像这样:

[1, [0], 'a', 1, [0], 'a'].replace([1, [0], 'a', 1], [5])

应该屈服

[5, [0], 'a']

请注意,此问题不是重复的,因为它们不需要匹配模式,而只需要匹配列表中的特定项目。

一个有效的解决方案,通过使用切片分配就地替换子列表:

def replace_list(lst,sublst,replacement):
lensub = len(sublst)
i = 0
while i <= len(lst)-lensub:
if lst[i:i+lensub] == sublst:
lst[i:i+lensub] = replacement
i += len(replacement)
else:
i += 1
lst = [1, [0], 'a', 1, [0], 'a']
replace_list(lst,[1, [0], 'a', 1], [5])

现在lst是:

[5, [0], 'a']

更复杂的输入(测试最终条件和多次替换(

lst = [1, [0], 'a', 1, 1, [0], 'a', 1, [0], 'a',1, [0], 'a', 1]

更换后的产量:

[5, 5, [0], 'a', 5]

工作原理:

  • 循环将要替换的列表切片为子列表的确切大小(使用 while 因为如果替换成列表会更改
  • 如果存在匹配项,请使用切片分配将切片替换为"替换和增加"计数器,以避免重叠替换

我对不断的列表切片不太满意,但这里需要它来执行与其他列表的相等,并且创建一个内部循环会更麻烦,而且不一定更快。

如果您不想就地工作,您可以在开始时创建一个副本,处理副本并返回它:

def replace_list(lst_,sublst,replacement):
lst = lst_.copy()
...
return lst

如果你使用ast.literal_eval那么你使用相同的字符串.replace

>>> from ast import literal_eval
>>> li=[1, [0], 'a', 1, [0], 'a']
>>> literal_eval(repr(li).replace("1, [0], 'a', 1", '5'))
[5, [0], 'a']

正如评论中指出的,你也可以使用 json 做类似的事情:

>>> import json
>>> json.loads(json.dumps(li).replace('1, [0], "a", 1','5'))
[5, [0], 'a']

递归,也许这不是一个好的解决方案,但它有效

lst = [1, [0], 'a', 1, 1, [0], 'a', 1, [0], 'a',1, [0], 'a', 1]
rep = [1, [0], 'a', 1]
numb = 5
def rep_lst(lst, sub, repl):
for i, x in enumerate(lst):
if x == repl[0] and lst[i:i+len(repl)] == repl:
lst = rep_lst(lst[:i] + [sub] +  lst[i+len(repl):], sub, repl)
return lst
print(rep_lst(lst, numb, rep))

输出

[5, 5, [0], 'a', 5]

以下解决方案有点牵强,但它来自以下假设:

方法str.replace很快,非常快。为什么不将列表转换为可以使用它的内容。

首先,我们需要编写一个帮助程序,该辅助程序将允许获取列表中可变元素的哈希值。

def make_hashable(item):
"""Convert an item to its hashable counterpart"""
try:
hash(item)
return item
except TypeError:
if isinstance(item, (list, tuple)):
return tuple(make_hashable(x) for x in item)
elif isinstance(item, set):
return frozenset(make_hashable(x) for x in item)
elif isinstance(item, dict):
return frozenset((k, make_hashable(v)) for k, v in item.items())
raise

我们现在可以编写翻译词典以转换为 O(n( 中的字符串表示并使用str.replace.

from itertools import count, chain
def list_replace(lst, sublst, repl):
counter = count(1)
item_to_char, char_to_item = {}, {chr(0): repl}
lst_chars, sublst_chars = [], []
# Create the str representation for lst
for item in lst:
item = make_hashable(item)
if item in item_to_char:
c = item_to_char[item]
else:
c = chr(next(counter))
item_to_char[item] = c
char_to_item[c] = [item]
lst_chars.append(c)
# Create the str representation for sublst
for item in sublst:
item = make_hashable(item)
if item in item_to_char:
c = item_to_char[item]
else:
return lst
sublst_chars.append(c)
lst_string = ''.join(lst_chars)
sublst_string = ''.join(sublst_chars)
# use str.replace
lst_string = lst_string.replace(sublst_string, chr(0))
# Convert back to a list
return list(chain(*map(char_to_item.get, lst_string)))

print(list_replace([1, [2], 3], [1, [2]], [6]))  # [6, 3]

相关内容

  • 没有找到相关文章