Python, лямбда, найти минимум - PullRequest
       73

Python, лямбда, найти минимум

5 голосов
/ 28 октября 2009

У меня есть функция foreach, которая вызывает указанную функцию для каждого элемента, который она содержит. Я хочу получить минимум из этих элементов, но я не знаю, как написать лямбда-функцию или функцию или даже класс, который будет управлять этим. Спасибо за любую помощь.


Я использую свою функцию foreach так:
o.foreach( lambda i: i.call() )

или

o.foreach( I.call )

Я не люблю составлять списки или другие объекты. Я хочу повторить через это и найти мин.

Мне удается написать класс, который думает, но должно быть какое-то лучшее решение, чем это:

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

Хорошо, я полагаю, что мой метод .foreach не является идеей Python. Я должен сделать свой класс повторяемым, потому что все ваши решения основаны на списках, и тогда все станет проще.

В C # не было бы проблем с лямбда-функцией, подобной этой, поэтому я подумал, что этот питон также очень мощный.

Ответы [ 6 ]

12 голосов
/ 28 октября 2009

Python имеет встроенную поддержку для поиска минимумов :

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

Если вам нужно сначала обработать список с помощью функции, вы можете сделать это с помощью map :

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

Или вы можете получить фантазию с списком и генератором выражений , например:

>>> min(double(x) for x in [1, 2, 3])
2
7 голосов
/ 28 октября 2009

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

l = [5,2,6,7,9,8]
reduce(lambda a,b: a if a < b else b, l[1:], l[0])
5 голосов
/ 28 октября 2009

Написание foreach метод не очень питонический. Вам лучше сделать его итератором, чтобы он работал со стандартными функциями Python, такими как min.

Вместо того, чтобы писать что-то вроде этого:

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

напишите это:

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

Теперь вы можете звонить min как min(myobj).

1 голос
/ 28 октября 2009

У меня есть функция foreach, которая вызывает указанную функцию для каждого элемента, который в ней содержится

Из комментария, который вы впоследствии разместили, звучит, что вы заново изобрели встроенную функцию map.

Похоже, вы ищете что-то вроде этого:

min(map(f, seq))

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

Как показывает gnibbler, если вы хотите найти значение x в последовательности, для которой f(x) возвращает наименьшее значение, вы можете использовать:

min(seq, key=f)

... если вы не хотите найти всех элементов в seq, для которых f возвращает наименьшее значение. Например, если seq является списком словарей,

min(seq, key=len)

вернет первый словарь в списке с наименьшим количеством элементов, а не все словари, содержащие это количество элементов.

Чтобы получить список всех элементов в последовательности, для которых функция f возвращает наименьшее значение, выполните следующее:

values = map(f, seq)
result = [seq[i] for (i, v) in enumerate(values) if v == min(values)]
1 голос
/ 28 октября 2009

Хорошо, вам нужно понять одну вещь: lambda создает функциональный объект для вас. Но так же, просто, обычный def. Посмотрите на этот пример:

lst = range(10)

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

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

print filter(is_even, lst)

Обе эти работы. Они дают одинаковый идентичный результат. lambda создает объект без имени; def делает объект именованной функции. filter() не волнует, имеет ли объект функции имя или нет.

Итак, если ваша единственная проблема с lambda заключается в том, что вы не можете использовать = в lambda, вы можете просто создать функцию, используя def.

Теперь, как говорится, я не предлагаю вам использовать ваш метод .foreach(), чтобы найти минимальное значение. Вместо этого заставьте ваш главный объект возвращать список значений и просто вызовите функцию Python min().

lst = range(10)
print min(lst)

РЕДАКТИРОВАТЬ: Я согласен, что ответ, который был принят, лучше. Вместо того, чтобы возвращать список значений, лучше определить __iter__() и сделать объект итеративным.

0 голосов
/ 28 октября 2009

Предположим, у вас есть

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

для минимального значения f

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

для значения х как минимум

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

конечно, вы можете использовать и лямбду

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

но это немного уродливо, карта здесь выглядит лучше

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

>>> min(seq,key=lambda x:x*x-2)
0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...