any() functie in Python met een callback

De Python-standaardbibliotheek definieert een any()functie die

Retourneer True als een element van de iterabele waar is. Als de iterabele leeg is, retourneer dan False.

Het controleert alleen of de elementen Trueopleveren. Wat ik wil dat het kan, dus een callback specificeren om te zien of een element bij de rekening past, zoals:

any([1, 2, 'joe'], lambda e: isinstance(e, int) and e > 0)

Antwoord 1, autoriteit 100%

Wat dacht je van:

>>> any(isinstance(e, int) and e > 0 for e in [1,2,'joe'])
True

Het werkt natuurlijk ook met all():

>>> all(isinstance(e, int) and e > 0 for e in [1,2,'joe'])
False

Antwoord 2, autoriteit 14%

elkefunctie retourneert True als een voorwaarde True is.

>>> any(isinstance(e, int) and e > 0 for e in [0 ,0, 1])
True # Returns True because 1 is greater than 0.
>>> any(isinstance(e, int) and e > 0 for e in [0 ,0, 0])
False # Returns False because not a single condition is True.

Eigenlijk is het concept van elkefunctie afkomstig van Lisp, of je kunt zeggen van de functie-programmeerbenadering. Er is nog een andere functie die er precies tegenover staat: alles

>>> all(isinstance(e, int) and e > 0 for e in [1, 33, 22])
True # Returns True when all the condition satisfies.
>>> all(isinstance(e, int) and e > 0 for e in [1, 0, 1])
False # Returns False when a single condition fails.

Deze twee functies zijn echt cool als ze op de juiste manier worden gebruikt.


Antwoord 3, autoriteit 9%

U zou een “generator-expressie” moeten gebruiken – dat wil zeggen, een taalconstructie die iterators kan verbruiken en filter en expressies daarop kan toepassen op een enkele regel:

Bijvoorbeeld (i ** 2 for i in xrange(10))is een generator voor het kwadraat van de eerste 10 natuurlijke getallen (0 tot 9)

Ze staan ​​ook een “if” -clausule toe om de itens op de “for” -clausule te filteren, dus voor uw voorbeeld kunt u het volgende gebruiken:

any (e for e in [1, 2, 'joe'] if isinstance(e, int) and e > 0)

Antwoord 4, autoriteit 6%

Kleine verbetering van het antwoord van Antoine P

>>> any(type(e) is int for e in [1,2,'joe'])
True

Voor all()

>>> all(type(e) is int for e in [1,2,'joe'])
False

Antwoord 5, autoriteit 4%

Terwijl de anderen goede Pythonische antwoorden gaven (in de meeste gevallen zou ik gewoon het geaccepteerde antwoord gebruiken), wilde ik er alleen op wijzen hoe gemakkelijk het is om je eigen hulpprogramma-functie te maken om dit zelf te doen als je er echt de voorkeur aan geeft:

def any_lambda(iterable, function):
  return any(function(i) for i in iterable)
In [1]: any_lambda([1, 2, 'joe'], lambda e: isinstance(e, int) and e > 0
Out[1]: True
In [2]: any_lambda([-1, '2', 'joe'], lambda e: isinstance(e, int) and e > 0)
Out[2]: False

Ik denk dat ik het op zijn minst eerst met de functieparameter zou definiëren, omdat dat beter overeenkomt met bestaande ingebouwde functies zoals map() en filter():

def any_lambda(function, iterable):
  return any(function(i) for i in iterable)

Antwoord 6, autoriteit 4%

Je kunt een combinatie van anyen mapgebruiken als je je lambda-notatie echt zo wilt houden:

any(map(lambda e: isinstance(e, int) and e > 0, [1, 2, 'joe']))

Maar het is beter om een ​​generator-expressie te gebruiken, omdat de hele lijst niet twee keer wordt opgebouwd.


Antwoord 7, autoriteit 3%

filter kan werken, en het geeft je de overeenkomende elementen terug

>>> filter(lambda e: isinstance(e, int) and e > 0, [1,2,'joe'])
[1, 2]

Antwoord 8, autoriteit 2%

Als u echteen lambda in any() wilt inlineeren, kunt u dit doen:

>>> any((lambda: isinstance(e, int))() for e in [1,2,'joe'])
True
>>> any((lambda: isinstance(e, int))() for e in ['joe'])
False

U hoeft alleen de naamloze lambda af te ronden en ervoor te zorgen dat deze bij elke passage wordt aangeroepen door de ()

toe te voegen

Het voordeel hier is dat je nog steeds kunt profiteren van het kortsluiten van de evaluatie van een wanneer je de eerste int raakt

Other episodes