Python: zoeken in lijst

Ik ben dit tegengekomen:

item = someSortOfSelection()
if item in myList:
    doMySpecialFunction(item)

maar soms werkt het niet met al mijn items, alsof ze niet in de lijst werden herkend (als het een lijst met strings is).

Is dit de meest ‘pythonische’ manier om een ​​item in een lijst te vinden: if x in l:?


Antwoord 1, autoriteit 100%

Wat je eerste vraag betreft: die code is prima in orde en zou moeten werken als item gelijk is aan een van de elementen in myList. Misschien probeer je een string te vinden die niet exact overeenkomt met een van de items of misschien gebruik je een float-waarde die onnauwkeurig is.

Wat betreft uw tweede vraag: er zijn eigenlijk verschillende manieren om dingen in lijsten te ‘vinden’.

Controleren of er iets in zit

Dit is het gebruik dat u beschrijft: controleren of iets in een lijst staat of niet. Zoals je weet, kun je daarvoor de operator in gebruiken:

3 in [1, 2, 3] # => True

Een verzameling filteren

Dat wil zeggen, alle elementen in een reeks vinden die aan een bepaalde voorwaarde voldoen. U kunt daarvoor lijstbegrip of generatoruitdrukkingen gebruiken:

matches = [x for x in lst if fulfills_some_condition(x)]
matches = (x for x in lst if x > 6)

De laatste zal een generator teruggeven die je je kunt voorstellen als een soort luie lijst die pas wordt opgebouwd zodra je er doorheen gaat. Trouwens, de eerste is precies gelijk aan

matches = filter(fulfills_some_condition, lst)

in Python 2. Hier kun je hogere-orde functies aan het werk zien. In Python 3 retourneert filter geen lijst, maar een generatorachtig object.

Het eerste exemplaar vinden

Als je alleen het eerste wilt dat overeenkomt met een voorwaarde (maar je weet nog niet wat het is), is het prima om een ​​for-lus te gebruiken (mogelijk ook met de else-clausule, wat niet echt bekend is). U kunt ook

next(x for x in lst if ...)

die de eerste overeenkomst retourneert of een StopIteration oplevert als er geen wordt gevonden. Als alternatief kunt u

next((x for x in lst if ...), [default value])

De locatie van een item vinden

Voor lijsten is er ook de index methode die soms handig kan zijn als je wilt weten waar een bepaald element in de lijst staat:

[1,2,3].index(2) # => 1
[1,2,3].index(4) # => ValueError

Houd er echter rekening mee dat als u duplicaten heeft, .index altijd de laagste index retourneert:……

[1,2,3,2].index(2) # => 1

Als er duplicaten zijn en u wilt alle indexen, dan kunt u in plaats daarvan enumerate() gebruiken:

[i for i,x in enumerate([1,2,3,2]) if x==2] # => [1, 3]

Antwoord 2, autoriteit 16%

Als u één element wilt vinden of None standaard in next wilt gebruiken, wordt StopIteration niet verhoogd als het item niet is gevonden in de lijst:

first_or_default = next((x for x in lst if ...), None)

Antwoord 3, autoriteit 2%

Hoewel het antwoord van Niklas B. behoorlijk uitgebreid is, is het soms handig om de index te krijgen als we een item in een lijst willen vinden:

next((i for i, x in enumerate(lst) if [condition on x]), [default value])

Antwoord 4

Het eerste exemplaar vinden

Er is een recept daarvoor in itertools:

def first_true(iterable, default=False, pred=None):
    """Returns the first true value in the iterable.
    If no true value is found, returns *default*
    If *pred* is not None, returns the first item
    for which pred(item) is true.
    """
    # first_true([a,b,c], x) --> a or b or c or x
    # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
    return next(filter(pred, iterable), default)

De volgende code vindt bijvoorbeeld het eerste oneven getal in een lijst:

>>> first_true([2,3,4,5], None, lambda x: x%2==1)
3  

Antwoord 5

Een ander alternatief: je kunt controleren of een item in een lijst staat met if item in list:, maar dit is volgorde O(n). Als je te maken hebt met grote lijsten met items en je alleen moet weten of iets op je lijst staat, kun je de lijst eerst naar een set converteren en profiteren van constante tijd ingesteld opzoeken:

my_set = set(my_list)
if item in my_set:  # much faster on average than using a list
    # do something

Het zal niet in alle gevallen de juiste oplossing zijn, maar in sommige gevallen kan dit betere prestaties opleveren.

Merk op dat het maken van de set met set(my_list) ook O(n) is, dus als je dit maar één keer hoeft te doen, is het niet sneller om het op deze manier te doen. Als u echter herhaaldelijk lidmaatschap moet controleren, is dit O(1) voor elke zoekopdracht na het maken van de eerste set.


Antwoord 6

Definitie en gebruik

de methode count() retourneert het aantal elementen met de opgegeven waarde.

Syntaxis

list.count(value)

voorbeeld:

fruits = ['apple', 'banana', 'cherry']
x = fruits.count("cherry")

Vraagvoorbeeld:

item = someSortOfSelection()
if myList.count(item) >= 1 :
    doMySpecialFunction(item)

Antwoord 7

Misschien wilt u een van de twee mogelijke zoekopdrachten gebruiken terwijl u met een lijst met tekenreeksen werkt:

  1. als lijstelement gelijk is aan een item (‘voorbeeld’ staat in
    [‘één’,’voorbeeld’,’twee’]):

    if item in your_list: some_function_on_true()

    ‘ex’ in [‘one’,’ex’,’two’] => True

    ‘ex_1’ in [‘one’,’ex’,’two’] => False

  2. als lijstelement zoals een item is (‘ex’ is in
    [‘een,’voorbeeld’,’twee’] of ‘voorbeeld_1’ is in
    [‘één’,’voorbeeld’,’twee’]):

    matches = [el for el in your_list if item in el]

    of

    matches = [el for el in your_list if el in item]

    controleer dan gewoon len(matches) of lees ze indien nodig.


Antwoord 8

In plaats van list.index(x) te gebruiken die de index van x retourneert als deze in de lijst wordt gevonden of een #ValueError-bericht retourneert als x niet wordt gevonden, je zou list.count(x) kunnen gebruiken die het aantal keren dat x in lijst voorkomt teruggeeft (validatie dat x inderdaad in de lijst staat) of anders 0 teruggeeft (bij afwezigheid van x). Het leuke van count() is dat het je code niet breekt of dat je een uitzondering moet maken voor als x niet wordt gevonden


Antwoord 9

Als je één keer wilt controleren of er waarde in het verzamelobject bestaat, is het prima om de ‘in’-operator te gebruiken. Als u echter meer dan eens gaat controleren, raad ik aan om de bisect-module te gebruiken. Houd er rekening mee dat het gebruik van bisect-modulegegevens moet worden gesorteerd. Dus je sorteert gegevens één keer en dan kun je bisect gebruiken. Het gebruik van de bisect-module op mijn machine is ongeveer 12 keer sneller dan het gebruik van de ‘in’-operator.

Hier is een voorbeeld van code die de syntaxis van Python 3.8 en hoger gebruikt:

import bisect
from timeit import timeit
def bisect_search(container, value):
    return (
      (index := bisect.bisect_left(container, value)) < len(container) 
      and container[index] == value
    )
data = list(range(1000))
# value to search
true_value = 666
false_value = 66666
# times to test
ttt = 1000
print(f"{bisect_search(data, true_value)=} {bisect_search(data, false_value)=}")
t1 = timeit(lambda: true_value in data, number=ttt)
t2 = timeit(lambda: bisect_search(data, true_value), number=ttt)
print("Performance:", f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")

Uitvoer:

bisect_search(data, true_value)=True bisect_search(data, false_value)=False
Performance: t1=0.0220, t2=0.0019, diffs t1/t2=11.71

Antwoord 10

je zei dat er in mijn verschillende onderzoeken misschien spaties waren en regelfeeds die stoorden. Daarom geef ik je deze oplossing.

myList=[" test","ok","ok1"]
item = "test"#someSortOfSelection()
if  True in list(map(lambda el : item in el ,myList)):
    doMySpecialFunction(item)

Antwoord 11

Controleer of er geen extra/ongewenste witruimte is in de items van de lijst met strings.
Dat is een reden die storend kan zijn omdat de items niet gevonden kunnen worden.


Antwoord 12

 lstr=[1, 2, 3]
 lstr=map(str,lstr)
 r=re.compile('^(3){1}')
 results=list(filter(r.match,lstr))
 print(results)

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes