2009-10-27 15 views
5

Tengo la función foreach que llama a la función especificada en cada elemento que contiene. Quiero obtener el mínimo de estos elementos, pero no tengo ni idea de cómo escribir lambda o función o incluso una clase que pueda manejar eso. Gracias por cada ayuda. Python, lambda, busque mínimo


uso mi función foreach así:

o.foreach(lambda i: i.call()) 

o

o.foreach(I.call) 

no me gustaría hacer una lista u otros objetos. Quiero iterar a través de él y encontrar mín.

me las arreglo para escribir una clase que haga el pensar, sino que debería haber alguna solución mejor que eso:

class Min:           
    def __init__(self,i):       
     self.i = i        
    def get_min(self):        
     return self.i         
    def set_val(self,o):        
     if o.val < self.i: self.i = o.val 

m = Min(xmin) 
self.foreach(m.set_val)        
xmin = m.get_min() 

Ok, así que supongo que mi método es .foreach idea no pitón. Debería hacer mi clase iterable porque todas sus soluciones están basadas en listas y todo será más fácil.

En C# no habría ningún problema con la función lambda así, así que pensé que python también es tan poderoso.

+3

¿Puede por favor publicar algún código de ejemplo de lo que tiene hasta ahora? – csl

+1

+1 para la etiqueta de tarea posible –

Respuesta

5

método de escritura foreach no es muy Pythonic. Debería hacerlo un iterador para que funcione con las funciones estándar de Python como min.

En lugar de escribir algo como esto:

def foreach(self, f): 
    for d in self._data: 
     f(d) 

escribir esto:

def __iter__(self): 
    for d in self._data: 
     yield d 

Ahora puede llamar min como min(myobj).

+0

¿Pero cómo funciona eso cuando rompo una iteración y la comienzo de nuevo? Comienza desde el principio o desde el momento en que se rompió? – qba

+0

Llama de nuevo a la función '__iter__' y eso devuelve un iterador nuevo sobre la información completa. –

12

Python ha incorporado en support for finding minimums:

>>> min([1, 2, 3]) 
1 

Si necesita procesar la lista con una primera función, se puede hacer eso con map:

>>> def double(x): 
... return x * 2 
... 
>>> min(map(double, [1, 2, 3])) 
2 

O puede conseguir la suposición con list comprehensions y generator expressions, por ejemplo:

>>> min(double(x) for x in [1, 2, 3]) 
2 
1

Bien, una cosa que necesita comprender: lambda crea un objeto de función para usted. Pero también lo hace simple, ordinario def. Mire este ejemplo:

lst = range(10) 

print filter(lambda x: x % 2 == 0, lst) 

def is_even(x): 
    return x % 2 == 0 

print filter(is_even, lst) 

Ambos funcionan. Producen el mismo resultado idéntico. lambda hace un objeto de función sin nombre; def crea un objeto de función nombrado. filter() no importa si el objeto de función tiene un nombre o no.

tanto, si su único problema con lambda es que no se puede utilizar en un =lambda, sólo puede crear una función utilizando def.

Ahora bien, dicho esto, no sugiero que use su método .foreach() para encontrar un valor mínimo. En cambio, haga que su objeto principal devuelva una lista de valores, y simplemente llame a la función Python min().

lst = range(10) 
print min(lst) 

EDIT: Acepto que la respuesta que se aceptó es mejor. En lugar de devolver una lista de valores, es mejor definir __iter__() y hacer el objeto iterable.

0

Suponga que tiene

>>> seq = range(-4,4) 
>>> def f(x): 
... return x*x-2 

para el valor mínimo de f

>>> min(f(x) for x in seq) 
-2 

por el valor de x en el mínimo

>>> min(seq, key=f) 
0 

por supuesto se puede utilizar lambda demasiado

>>> min((lambda x:x*x-2)(x) for x in range(-4,4)) 
-2 

pero que es un poco feo, mapa se ve mejor aquí

>>> min(map(lambda x:x*x-2, seq)) 
-2 

>>> min(seq,key=lambda x:x*x-2) 
0 
1

Tengo función foreach, que llama a la función especificada en cada elemento que contiene

Suena, del comentario posteriormente publicó, que ha reinventado la función incorporada map.

Parece que usted está buscando algo como esto:

min(map(f, seq)) 

donde f es la función que desea llamar en cada elemento de la lista.

Como muestra gnibbler, si usted quiere encontrar el valor x en la secuencia para la que f(x) devuelve el valor más bajo, puede utilizar:

min(seq, key=f) 

... a menos que usted quiere encontrar todos de los artículos en seq para los cuales f devuelve el valor más bajo. Por ejemplo, si seq es una lista de los diccionarios,

min(seq, key=len) 

devolverá el primer diccionario en la lista con el menor número de elementos, no todos los diccionarios que contienen ese número de artículos.

Para obtener una lista de todos los elementos de una secuencia para la que la función f devuelve el valor más pequeño, haga esto:

values = map(f, seq) 
result = [seq[i] for (i, v) in enumerate(values) if v == min(values)] 
+0

Debe evaluar el mínimo una vez antes de la comprensión de la lista en lugar de evaluar una y otra vez cada iteración dentro de la lista de comprensión. Aparte de eso, es una buena respuesta. – blubberdiblub

6

No se puede hacer esto con foreach y una lambda. Si desea hacer esto en un estilo funcional sin utilizar realmente min, encontrará que reduce es bastante similar a la función que estaba tratando de definir.

l = [5,2,6,7,9,8] 
reduce(lambda a,b: a if a < b else b, l[1:], l[0]) 
Cuestiones relacionadas