qba
qba

Reputation: 1311

Python, lambda, find minimum

I have foreach function which calls specified function on every element which it contains. I want to get minimum from thise elements but I have no idea how to write lambda or function or even a class that would manage that. Thanks for every help.


I use my foreach function like this:

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

or

o.foreach( I.call )

I don't like to make a lists or other objects. I want to iterate trough it and find min.

I manage to write a class that do the think but there should be some better solution than that:

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, so I suppose that my .foreach method is non-python idea. I should do my Class iterable because all your solutions are based on lists and then everything will become easier.

In C# there would be no problem with lambda function like that, so I though that python is also that powerful.

Upvotes: 6

Views: 23799

Answers (7)

AlwaysReady
AlwaysReady

Reputation: 1

You can use this:

x = lambda x,y,z: min(x,y,z)
print(x(3,2,1))

Upvotes: -1

steveha
steveha

Reputation: 76725

Okay, one thing you need to understand: lambda creates a function object for you. But so does plain, ordinary def. Look at this example:

lst = range(10)

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

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

print filter(is_even, lst)

Both of these work. They produce the same identical result. lambda makes an un-named function object; def makes a named function object. filter() doesn't care whether the function object has a name or not.

So, if your only problem with lambda is that you can't use = in a lambda, you can just make a function using def.

Now, that said, I don't suggest you use your .foreach() method to find a minimum value. Instead, make your main object return a list of values, and simply call the Python min() function.

lst = range(10)
print min(lst)

EDIT: I agree that the answer that was accepted is better. Rather than returning a list of values, it is better to define __iter__() and make the object iterable.

Upvotes: 1

Anand Chitipothu
Anand Chitipothu

Reputation: 4377

Writing foreach method is not very pythonic. You should better make it an iterator so that it works with standard python functions like min.

Instead of writing something like this:

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

write this:

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

Now you can call min as min(myobj).

Upvotes: 5

Chuck
Chuck

Reputation: 237080

You can't do this with foreach and a lambda. If you want to do this in a functional style without actually using min, you'll find reduce is pretty close to the function you were trying to define.

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

Upvotes: 7

Robert Rossney
Robert Rossney

Reputation: 96830

I have foreach function which calls specified function on every element which it contains

It sounds, from the comment you subsequently posted, that you have re-invented the built-in map function.

It sounds like you're looking for something like this:

min(map(f, seq))

where f is the function that you want to call on every item in the list.

As gnibbler shows, if you want to find the value x in the sequence for which f(x) returns the lowest value, you can use:

min(seq, key=f)

...unless you want to find all of the items in seq for which f returns the lowest value. For instance, if seq is a list of dictionaries,

min(seq, key=len)

will return the first dictionary in the list with the smallest number of items, not all dictionaries that contain that number of items.

To get a list of all items in a sequence for which the function f returns the smallest value, do this:

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

Upvotes: 1

John La Rooy
John La Rooy

Reputation: 304355

Suppose you have

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

for the minimum value of f

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

for the value of x at the minimum

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

of course you can use lambda too

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

but that is a little ugly, map looks better here

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

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

Upvotes: 0

Ryan Bright
Ryan Bright

Reputation: 3565

Python has built-in support for finding minimums:

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

If you need to process the list with a function first, you can do that with map:

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

Or you can get fancy with list comprehensions and generator expressions, for example:

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

Upvotes: 13

Related Questions