Python: для каждого элемента списка применить функцию по всему списку - PullRequest
25 голосов
/ 29 января 2009

Учитывая [1,2,3,4,5], как я могу сделать что-то вроде

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

Я хотел бы сохранить все результаты, найти минимум и вернуть два числа, использованных для нахождения минимума. Так что в случае, который я описал выше, я хотел бы вернуть (1,5).

Так что в основном я хотел бы сделать что-то вроде

для каждого элемента i в списке сопоставить некоторую функцию со всеми элементами в списке, взяв i и j в качестве параметров сохранить результат в главном списке, найти минимальное значение в главном списке и вернуть аргументы i, j, использованные для вычисления этого минимального значения.

В моей реальной задаче у меня есть список объектов / координат, и функция, которую я использую, берет две координаты и вычисляет евклидово расстояние. Я пытаюсь найти минимальное евклидово расстояние между любыми двумя точками, но мне не нужен причудливый алгоритм.

Ответы [ 7 ]

42 голосов
/ 30 января 2009

Вы можете сделать это, используя список значений и min () (код 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)

Обратите внимание, что для запуска этого на Python 2.5 вам нужно либо сделать один из аргументов плавающим, либо сделать from __future__ import division, чтобы 1/5 правильно равнялось 0,2 вместо 0.

10 голосов
/ 30 января 2009

Если я правильно понял, что вы хотите найти минимальное значение функции для всех возможных пар из 2 элементов из списка ...

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)
3 голосов
/ 30 января 2009

Если вы не против импортировать пакет numpy, в него встроено много удобных функций. Вероятно, гораздо эффективнее использовать их структуры данных, чем списки списков и т. Д.

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]
3 голосов
/ 30 января 2009

Некоторый читаемый питон:

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

Дайте мне знать, если что-то не понятно.

1 голос
/ 30 января 2009

Если вы работаете с Python ≥2.6 (включая 3.x), вы можете:

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

РЕДАКТИРОВАТЬ: Теперь, когда я думаю об этом и если я правильно помню свою математику, это также должно дать ответ, предполагая, что все числа неотрицательны:

def getmin(alist):
    return min(alist), max(alist)
1 голос
/ 30 января 2009

Делая это математикой ...

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

Если, конечно, у вас нет негативов там. В этом случае это не сработает, потому что вы действительно хотите минимальное и максимальное абсолютные значения - числитель должен быть близок к нулю, а знаменатель - далеко от него, в любом направлении. И двойные негативы сломали бы его.

0 голосов
/ 23 ноября 2009
>>> 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)
...