简体   繁体   English

Python:在列表中查找替换

[英]Python: Find-replace on lists

I first want to note that my question is different from what's in this link: finding and replacing elements in a list (python) 我首先要注意,我的问题与此链接的内容不同: 在列表中查找和替换元素(python)

What I want to ask is whether there is some known API or conventional way to achieve such a functionality (If it's not clear, a function/method like my imaginary list_replace() is what I'm looking for): 我想问的是,是否有某种已知的API或常规方法来实现这种功能(如果不清楚,我list_replace()是像我想象中的list_replace()这样的函数/方法):

>>> list = [1, 2, 3]
>>> list_replace(list, 3, [3, 4, 5])
>>> list
[1, 2, 3, 4, 5]

An API with limitation of number of replacements will be better: 受替换次数限制的API会更好:

>>> list = [1, 2, 3, 3, 3]
>>> list_replace(list, 3, [8, 8], 2)
>>> list
[1, 2, 8, 8, 8, 8, 3]

And another optional improvement is that the input to replace will be a list itself, instead of a single value: 另一个可选的改进是要替换的输入将是列表本身,而不是单个值:

>>> list = [1, 2, 3, 3, 3]
>>> list_replace(list, [2, 3], [8, 8], 2)
>>> list
[1, 8, 8, 3, 3]

Is there any API that looks at least similar and performs these operations, or should I write it myself? 是否有看起来至少相似并执行这些操作的API,还是我应该自己编写?

Try; 尝试;

def list_replace(ls, val, l_insert, num = 1):
    l_insert_len = len(l_insert)
    indx = 0
    for i in range(num):
        indx = ls.index(val, indx) #it throw value error if it cannot find an index
        ls = ls[:indx] + l_insert + ls[(indx + 1):]
        indx += l_insert_len
    return ls

This function works for both first and second case; 此功能适用于第一种情况和第二种情况;
It wont work with your third requirement 它不能满足您的第三个要求

Demo 演示

>>> list = [1, 2, 3]
>>> list_replace(list, 3, [3, 4, 5])
[1, 2, 3, 4, 5]
>>> list = [1, 2, 3, 3, 3]
>>> list_replace(list, 3, [8, 8], 2)
[1, 2, 8, 8, 8, 8, 3]

Note It returns a new list; 注意它将返回一个新列表; The list passed in will not change. 传入的列表不会更改。

how about this, it work for the 3 requirements 怎么样,它可以满足3个要求

def list_replace(origen,elem,new,cantidad=None):
    n=0
    resul=list()
    len_elem=0
    if isinstance(elem,list):
        len_elem=len(elem)
    for i,x in enumerate(origen):
        if x==elem or elem==origen[i:i+len_elem]:
            if cantidad and n<cantidad:
                resul.extend(new)
                n+=1
                continue
            elif not cantidad:
                resul.extend(new)
                continue
        resul.append(x)
    return resul



>>>list_replace([1,2,3,4,5,3,5,33,23,3],3,[42,42])
[1, 2, 42, 42, 4, 5, 42, 42, 5, 33, 23, 42, 42]
>>>list_replace([1,2,3,4,5,3,5,33,23,3],3,[42,42],2)
[1, 2, 42, 42, 4, 5, 42, 42, 5, 33, 23, 3]
>>>list_replace([1,2,3,4,5,3,5,33,23,3],[33,23],[42,42,42],2)
[1, 2, 3, 4, 5, 3, 5, 42, 42, 42, 23, 3]

Given this isn't hard to write, and not a very common use case, I don't think it will be in the standard library. 鉴于这并不难编写,也不是很常见的用例,所以我认为它不会出现在标准库中。 What would it be named, replace_and_flatten ? 它将被命名为replace_and_flatten It's quite hard to explain what that does, and justify the inclusion. 很难解释这样做是什么,并证明包含是否合理。

Explicit is also better than implicit, so... 显式也比隐式好,所以...

def replace_and_flatten(lst, searched_item, new_list):
    def _replace():
        for item in lst:
            if item == searched_item:
                yield from new_list  # element matches, yield all the elements of the new list instead
            else:
                yield item  # element doesn't match, yield it as is

    return list(_replace())  # convert the iterable back to a list

I developed my own function, you are welcome to use and to review it. 我开发了自己的功能,欢迎您使用和审查。

Note that in contradiction to the examples in the question - my function creates and returns a new list. 请注意,与问题中的示例相反,我的函数创建并返回了一个新列表。 It does not modify the provided list. 修改提供的列表。

Working examples: 工作示例:

list = [1, 2, 3]
l2 = list_replace(list, [3], [3, 4, 5])
print('Changed: {0}'.format(l2))
print('Original: {0}'.format(list))

list = [1, 2, 3, 3, 3]
l2 = list_replace(list, [3], [8, 8], 2)
print('Changed: {0}'.format(l2))
print('Original: {0}'.format(list))

list = [1, 2, 3, 3, 3]
l2 = list_replace(list, [2, 3], [8, 8], 2)
print('Changed: {0}'.format(l2))
print('Original: {0}'.format(list))

I always print also the original list, so you can see that it is not modified: 我也总是打印原始列表,因此您可以看到它没有被修改:

Changed: [1, 2, 3, 4, 5]
Original: [1, 2, 3]
Changed: [1, 2, 8, 8, 8, 8, 3]
Original: [1, 2, 3, 3, 3]
Changed: [1, 8, 8, 3, 3]
Original: [1, 2, 3, 3, 3]

Now, the code (tested with Python 2.7 and with Python 3.4): 现在,代码(经过Python 2.7和Python 3.4测试):

def list_replace(lst, source_sequence, target_sequence, limit=0):
    if limit < 0:
        raise Exception('A negative replacement limit is not supported')
    source_sequence_len = len(source_sequence)
    target_sequence_len = len(target_sequence)
    original_list_len = len(lst)
    if source_sequence_len > original_list_len:
        return list(lst)
    new_list = []
    i = 0
    replace_counter = 0
    while i < original_list_len:
        suffix_is_long_enough = source_sequence_len <= (original_list_len - i)
        limit_is_satisfied = (limit == 0 or replace_counter < limit)
        if suffix_is_long_enough and limit_is_satisfied:
            if lst[i:i + source_sequence_len] == source_sequence:
                new_list.extend(target_sequence)
                i += source_sequence_len
                replace_counter += 1
                continue
        new_list.append(lst[i])
        i += 1      
    return new_list

I developed a function for you (it works for your 3 requirements): 我为您开发了一个功能(它可以满足您的3个要求):

def list_replace(lst,elem,repl,n=0):
    ii=0
    if type(repl) is not list:
        repl = [repl]
    if type(elem) is not list:
        elem = [elem]
    if type(elem) is list:
        length = len(elem)
    else:
        length = 1
    for i in range(len(lst)-(length-1)):
        if ii>=n and n!=0:
            break
        e = lst[i:i+length]
        if e==elem:
            lst[i:i+length] = repl
            if n!=0:
                ii+=1
    return lst

I've tried with your examples and it works ok. 我已经尝试了您的示例,但效果很好。

Tests made: 进行的测试:

print list_replace([1,2,3], 3, [3, 4, 5])
print list_replace([1, 2, 3, 3, 3], 3, [8, 8], 2)
print list_replace([1, 2, 3, 3, 3], [2, 3], [8, 8], 2)

NOTE: never use list as a variable. 注意:永远不要将list用作变量。 I need that object to do the is list trick. 我需要该对象来执行is list技巧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM