Elementen zoeken en vervangen in een lijst

Ik moet door een lijst zoeken en alle gebeurtenissen van één element vervangen door een ander. Tot nu toe krijgen mijn pogingen in de code me nergens, wat is de beste manier om dit te doen?

Stel bijvoorbeeld dat mijn lijst de volgende gehele getallen heeft

>>> a = [1,2,3,4,5,1,2,3,4,5,1]

en ik moet alle voorkomens van het nummer 1 vervangen door de waarde 10, zodat de uitvoer die ik nodig heb

>>> a = [10, 2, 3, 4, 5, 10, 2, 3, 4, 5, 10]

Dus mijn doel is om alle instanties van het nummer 1 te vervangen door het nummer 10.


1, Autoriteit 100%

>>> a= [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1]
>>> for n, i in enumerate(a):
...   if i == 1:
...      a[n] = 10
...
>>> a
[10, 2, 3, 4, 5, 10, 2, 3, 4, 5, 10]

2, Autoriteit 202%

Probeer een lijst begrijpen en de Ternaire operator .

>>> a=[1,2,3,1,3,2,1,1]
>>> [4 if x==1 else x for x in a]
[4, 2, 3, 4, 3, 2, 4, 4]

3, Autoriteit 22%

Als u verschillende waarden hebt om te vervangen, kunt u ook een woordenboek gebruiken:

a = [1, 2, 3, 4, 1, 5, 3, 2, 6, 1, 1]
dic = {1:10, 2:20, 3:'foo'}
print([dic.get(n, n) for n in a])
> [10, 20, 'foo', 4, 10, 5, 'foo', 20, 6, 10, 10]

Antwoord 4, autoriteit 13%

Het begrijpen van de lijst werkt goed, en het doorlopen met enumerate kan u wat geheugen besparen (omdat de bewerking in wezen op zijn plaats wordt uitgevoerd).

Er is ook functionele programmering. Zie het gebruik van kaart:

>>> a = [1,2,3,2,3,4,3,5,6,6,5,4,5,4,3,4,3,2,1]
>>> map(lambda x: x if x != 4 else 'sss', a)
[1, 2, 3, 2, 3, 'sss', 3, 5, 6, 6, 5, 'sss', 5, 'sss', 3, 'sss', 3, 2, 1]

Antwoord 5, autoriteit 7%

Hier is een cool en schaalbaar ontwerppatroon dat in O(n)tijd draait…

a = [1,2,3,4,5,6,7,6,5,4,3,2,1]
replacements = {
    1: 10,
    2: 20,
    3: 30,
}
a = [replacements.get(x, x) for x in a]
print(a)
# Returns [10, 20, 30, 4, 5, 6, 7, 6, 5, 4, 30, 20, 10]

Antwoord 6, autoriteit 4%

>>> a=[1,2,3,4,5,1,2,3,4,5,1]
>>> item_to_replace = 1
>>> replacement_value = 6
>>> indices_to_replace = [i for i,x in enumerate(a) if x==item_to_replace]
>>> indices_to_replace
[0, 5, 10]
>>> for i in indices_to_replace:
...     a[i] = replacement_value
... 
>>> a
[6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6]
>>> 

Antwoord 7, autoriteit 4%

a = [1,2,3,4,5,1,2,3,4,5,1,12]
for i in range (len(a)):
    if a[i]==2:
        a[i]=123

U kunt een for en of while-lus gebruiken; als u echter de ingebouwde Enumerate-functie kent, wordt aanbevolen om Enumerate te gebruiken.1


Antwoord 8, autoriteit 3%

Om eenvoudig alle 1te vervangen door 10in
a = [1,2,3,4,5,1,2,3,4,5,1]men zou de volgende eenregelige lambda+kaartcombinatie kunnen gebruiken, en ‘Kijk, Ma , geen IF’s of FOR’s!’ :

# This substitutes all '1' with '10' in list 'a' and places result in list 'c':

c = list(map(lambda b: b.replace("1","10"), a))


Antwoord 9, autoriteit 3%

één voering en de snelste manier om dit te doen:

[10 if x==1 else x for x in a]

Antwoord 10, autoriteit 2%

Bij lange lijsten en zeldzame gevallen is het ongeveer 3x sneller met list.index()– vergeleken met iteratiemethoden in één stap die in de andere antwoorden worden gepresenteerd.

def list_replace(lst, old=1, new=10):
    """replace list elements (inplace)"""
    i = -1
    try:
        while 1:
            i = lst.index(old, i + 1)
            lst[i] = new
    except ValueError:
        pass

Antwoord 11, autoriteit 2%

Het volgende is een zeer eenvoudige methode in Python 3.x

a = [1,2,3,4,5,1,2,3,4,5,1]        #Replacing every 1 with 10
 for i in range(len(a)):
   if a[i] == 1:
     a[i] = 10  
 print(a)

Deze methode werkt. Opmerkingen zijn welkom. Ik hoop dat het helpt 🙂

Probeer ook te begrijpen hoe Outis’s en Damzam’s oplossingen werken. Lijstcompressies en Lambda-functie zijn nuttige hulpmiddelen.


12, Autoriteit 2%

Ik weet dat dit een heel oude vraag is en er is een groot aantal manieren om het te doen. De eenvoudiger die ik heb gevonden, gebruikt numpyPackage.

import numpy
arr = numpy.asarray([1, 6, 1, 9, 8])
arr[ arr == 8 ] = 0 # change all occurrences of 8 by 0
print(arr)

13, Autoriteit 2%

Mijn usecase vervangt Nonemet een aantal standaardwaarde.

Ik heb getimede benaderingen van dit probleem dat hier werden gepresenteerd, inclusief de ene door @kxr – met str.count.

Testcode in Ipython met Python 3.8.1:

def rep1(lst, replacer = 0):
    ''' List comprehension, new list '''
    return [item if item is not None else replacer for item in lst]
def rep2(lst, replacer = 0):
    ''' List comprehension, in-place '''    
    lst[:] =  [item if item is not None else replacer for item in lst]
    return lst
def rep3(lst, replacer = 0):
    ''' enumerate() with comparison - in-place '''
    for idx, item in enumerate(lst):
        if item is None:
            lst[idx] = replacer
    return lst
def rep4(lst, replacer = 0):
    ''' Using str.index + Exception, in-place '''
    idx = -1
    # none_amount = lst.count(None)
    while True:
        try:
            idx = lst.index(None, idx+1)
        except ValueError:
            break
        else:
            lst[idx] = replacer
    return lst
def rep5(lst, replacer = 0):
    ''' Using str.index + str.count, in-place '''
    idx = -1
    for _ in range(lst.count(None)):
        idx = lst.index(None, idx+1)
        lst[idx] = replacer
    return lst
def rep6(lst, replacer = 0):
    ''' Using map, return map iterator '''
    return map(lambda item: item if item is not None else replacer, lst)
def rep7(lst, replacer = 0):
    ''' Using map, return new list '''
    return list(map(lambda item: item if item is not None else replacer, lst))
lst = [5]*10**6
# lst = [None]*10**6
%timeit rep1(lst)    
%timeit rep2(lst)    
%timeit rep3(lst)    
%timeit rep4(lst)    
%timeit rep5(lst)    
%timeit rep6(lst)    
%timeit rep7(lst)    

Ik krijg:

26.3 ms ± 163 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
29.3 ms ± 206 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
33.8 ms ± 191 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
11.9 ms ± 37.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
11.9 ms ± 60.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
260 ns ± 1.84 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
56.5 ms ± 204 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Gebruik van de interne str.indexis in feite sneller dan elke handmatige vergelijking.

Ik wist niet of de uitzondering in test 4 arbeider zou zijn dan het gebruik van str.count, het verschil lijkt te verwaarloosbaar.

Merk op dat map()(test 6) een iterator retourneert en geen daadwerkelijke lijst, dus test 7.


14

U kunt eenvoudigweg het begrip in Python gebruiken:

def replace_element(YOUR_LIST, set_to=NEW_VALUE):
    return [i
            if SOME_CONDITION
            else NEW_VALUE
            for i in YOUR_LIST]

Voor uw zaak, waar u alle voorkomens van 1 met 10 wilt vervangen, is het Code Fragment zo:

def replace_element(YOUR_LIST, set_to=10):
    return [i
            if i != 1  # keeps all elements not equal to one
            else set_to  # replaces 1 with 10
            for i in YOUR_LIST]

Other episodes