2009-01-29 14 views
25

Compte tenu [1,2,3,4,5], comment puis-je faire quelque chose commePython: Pour chaque élément de la liste appliquer une fonction dans la liste

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 

Je voudrais stocker tous les résultats, trouver le minimum, et renvoyer les deux numéros utilisés pour trouver le minimum. Donc, dans le cas que j'ai décrit ci-dessus, je voudrais retourner (1,5).

Donc, fondamentalement, je voudrais faire quelque chose comme

pour chaque élément i dans la liste carte une fonction dans tous les éléments de la liste, en prenant i et j comme paramètres stocker le résultat dans une liste maîtresse, recherchez la valeur minimale dans la liste principale et renvoyez les arguments i, j utilisés pour calculer cette valeur minimale.

Dans mon vrai problème j'ai une liste objets/coordonnées, et la fonction que j'utilise prend deux coordonnées et calcule la distance euclidienne. J'essaie de trouver la distance euclidienne minimale entre deux points, mais je n'ai pas besoin d'un algorithme de fantaisie.

Répondre

42

Vous pouvez le faire en utilisant list comprehensions et min() (code Python 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) 

Notez que pour exécuter sur Python 2.5, vous devrez soit faire l'un des arguments d'un flotteur, ou faire from __future__ import division de sorte que 1/5 est égal à 0,2 correctement au lieu de 0.

+1

Notez que l'argument 'clé' de min n'est accepté que depuis 2.5 –

+0

J'aurais utilisé zip (nums, nums) au lieu de listcomp, mais sinon cela aurait été ma solution. –

+1

En fait, zip (nums, nums) donne [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], ce qui n'est pas correct. – Kiv

3

Certains python lisible:

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]) 

Laissez-moi savoir si quelque chose n'est pas clair.

10

Si je ne me trompe pas en pensant que vous voulez trouver la valeur minimale d'une fonction pour toutes les paires possibles de 2 éléments d'une liste ...

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

Listes nommées "l "Flippez-moi un peu. Bonne solution cependant :) – Kiv

+0

Oui, j'appelle toujours mes listes génériques 'lst'. –

+0

Je voudrais ajouter un [1:] à la fin: print min ((1. * i/j, i, j) pour i dans l pour j dans l) [1:] –

2

il Faire la manière ... mathy

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

Sauf, bien sûr, vous avez des négatifs là-dedans. Dans ce cas, cela ne fonctionnera pas parce que vous voulez réellement les valeurs absolues min et max - le numérateur devrait être proche de zéro, et le dénominateur loin de lui, dans les deux sens. Et les doubles négatifs le briseraient.

+0

BTW, ne fait pas ce que la question demande. Oui, c'est la solution à l'exemple simple dans la question, mais cela ne dit pas comment appliquer une fonction à des paires de nombres. (Ou peut-être que la question a été améliorée après que cette réponse a été postée.) – ToolmakerSteve

3

Si vous ne vous dérange pas d'importer le paquet numpy, il a beaucoup de fonctionnalités pratiques intégrées. Il est susceptible d'être d'utiliser beaucoup plus efficace leurs structures de données que les listes de listes, 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 vous travaillez avec Python ≥2.6 (y compris 3.x), vous pouvez:

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: maintenant que je pense et si je me souviens cela devrait aussi donner correctement mes mathématiques, la réponse en supposant que tous les numéros sont non négatifs:

+1

Si l'OP veut calculer la distance euclidienne, il y a le générateur itertools.combinations qui ne donnera que des paires uniques de valeurs différentes de l'entrée. – liori

+0

@liori: l'OP ne semble pas vouloir de distances euclidiennes. Merci pour votre commentaire, de toute façon, car cela m'a rappelé la question. – 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) 
Questions connexes