tags:

views:

1121

answers:

6

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.

+6  A: 

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
Ryan Bright
+1  A: 

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.

steveha
A: 

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
gnibbler
A: 

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)]
Robert Rossney
+3  A: 

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])
Chuck
+4  A: 

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

Anand Chitipothu
But how that works when I break an iteration and start it again?It starts from the begin or from the moment it was broken?
qba
It calls the `__iter__` function again and that returns a fresh iterator over the entire data.
Anand Chitipothu