2009-01-29 11 views
25

Dado [1,2,3,4,5], ¿cómo puedo hacer algo comoPython: Para cada elemento de la lista se aplica una función a través de la lista de

1/1, 1/2, 1/3,1/4,1/5, ...., 3/1,3/2,3/3,3/4,3/5,.... 5/1,5/2,5/3,5/4,5/5 

me gustaría para almacenar todos los resultados, encontrar el mínimo, y devolver los dos números usados para encontrar el mínimo. Entonces, en el caso que describí anteriormente, me gustaría devolver (1,5).

Así que básicamente me gustaría hacer algo como

para cada elemento i en la lista asignar alguna función en todos los elementos de la lista, teniendo i y j como parámetros Depositar el resultado en una lista maestra, encuentre el valor mínimo en la lista maestra y devuelva los argumentos i, j utilizados para calcular este valor mínimo.

En mi problema real tengo una lista de objetos/coordenadas, y la función que estoy usando toma dos coordenadas y calcula la distancia euclidiana. Estoy tratando de encontrar una distancia euclidiana mínima entre dos puntos, pero no necesito un algoritmo elegante.

Respuesta

42

Usted puede hacer esto utilizando list comprehensions y min() (Python código 3.0):

>>> nums = [1,2,3,4,5] 
>>> [(x,y) for x in nums for y in nums] 
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)] 
>>> min(_, key=lambda pair: pair[0]/pair[1]) 
(1, 5) 

Tenga en cuenta que ejecutar esto en Python 2.5 que necesita para hacer que sea uno de los argumentos de un flotador, o hacer from __future__ import division de manera que es igual a 1/5 correctamente 0,2 en lugar de 0.

+1

Tenga en cuenta que el argumento 'clave' en min solo se acepta desde 2.5 –

+0

Hubiera usado zip (nums, nums) en lugar de listcomp, pero de lo contrario, esa habría sido mi solución. –

+1

En realidad, zip (nums, nums) resulta en [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], lo que no es correcto. – Kiv

3

Algunos pitón legible:

def JoeCalimar(l): 
    masterList = [] 
    for i in l: 
     for j in l: 
      masterList.append(1.*i/j) 
    pos = masterList.index(min(masterList)) 
    a = pos/len(masterList) 
    b = pos%len(masterList) 
    return (l[a],l[b]) 

Avísame si algo no está claro.

10

Si estoy en lo cierto al pensar que usted quiere encontrar el valor mínimo de una función para todos los pares posibles de 2 elementos de una lista ...

l = [1,2,3,4,5] 

def f(i,j): 
    return i+j 

# Prints min value of f(i,j) along with i and j 
print min((f(i,j),i,j) for i in l for j in l) 
+0

Listas llamadas "l "enloquece un poco. Buena solución, aunque :) – Kiv

+0

Sí, siempre llamo a mis listas genéricas 'lst'. –

+0

Agregaría un [1:] al final: imprima min ((1. * i/j, i, j) para i en l para j en l) [1:] –

2

Hacerlo de la manera mathy ...

nums = [1, 2, 3, 4, 5] 
min_combo = (min(nums), max(nums)) 

A menos que, por supuesto, tenga negativos allí. En ese caso, esto no funcionará porque realmente quiere los valores absolutos mínimo y máximo: el numerador debe estar cerca de cero y el denominador alejado de él, en cualquier dirección. Y los dobles negativos lo romperían.

+0

Por cierto, no hace lo que se pregunta. Sí, es la solución al ejemplo simple en la pregunta, pero no dice cómo aplicar alguna función a pares de números. (O tal vez la pregunta se mejoró después de que se publicó esta respuesta.) – ToolmakerSteve

3

Si no le importa importar el paquete numpy, que tiene una gran cantidad de funcionalidad incorporada conveniente. Es probable que sea mucho más eficiente utilizar sus estructuras de datos de listas de listas, etc.

from __future__ import division 

import numpy 

data = numpy.asarray([1,2,3,4,5]) 
dists = data.reshape((1,5))/data.reshape((5,1)) 

print dists 

which = dists.argmin() 
(r,c) = (which // 5, which % 5) # assumes C ordering 

# pick whichever is most appropriate for you... 
minval = dists[r,c] 
minval = dists.min() 
minval = dists.ravel()[which] 
1

Si se trabaja con Python ≥2.6 (incluyendo 3.x), se puede:

from __future__ import division 
import operator, itertools 

def getmin(alist): 
    return min(
     (operator.div(*pair), pair) 
     for pair in itertools.product(alist, repeat=2) 
    )[1] 

getmin([1, 2, 3, 4, 5]) 

EDIT: Ahora que lo pienso, y si no recuerdo mis matemáticas correctamente, esto también debería dar la respuesta asumiendo que todos los números no son negativos:

def getmin(alist): 
    return min(alist), max(alist) 
+1

Si el OP desea calcular la distancia euclidiana, hay un generador de combinaciones itertools.com que generará solo pares únicos de valores diferentes de la entrada. – liori

+0

@liori: el OP no parece querer distancias euclidianas. Gracias por su comentario, de todos modos, ya que me recordó la pregunta. – tzot

0
>>> nums = [1, 2, 3, 4, 5]  
>>> min(map((lambda t: ((float(t[0])/t[1]), t)), ((x, y) for x in nums for y in nums)))[1] 
(1, 5) 
Cuestiones relacionadas