A
Alan McIntyre
Thanks to everybody that responded; I appreciate all the input, even if
I didn't respond to all of it individually.![Smile :) :)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
I didn't respond to all of it individually.
Mike said:Alan McIntyre wrote:
...
I have a list of items that has contiguous repetitions of values, but
the number and location of the repetitions is not important, so I just
need to strip them out. For example, if my original list is
[0,0,1,1,1,2,2,3,3,3,2,2,2,4,4,4,5], I want to end up with
[0,1,2,3,2,4,5].
...
Is there an elegant way to do this, or should I just stick with the
code above?
def changes( dataset ):
... last = None
... for value in dataset:
... if value != last:
... yield value
... last = value
... >>> print list(changes(data ))
which is quite readable/elegant IMO.
But fails if the list starts with None:
py> lst = [None,0,0,1,1,1,2,2,3,3,3,2,2,2,4,4,4,5]
py> def changes(dataset):
... last = None
... for value in dataset:
... if value != last:
... yield value
... last = value
...
py> list(changes(lst))
[0, 1, 2, 3, 2, 4, 5]
A minor modification that does appear to work:
py> def changes(dataset):
... last = object()
... for value in dataset:
... if value != last:
... yield value
... last = value
...
py> list(changes(lst))
[None, 0, 1, 2, 3, 2, 4, 5]
STeVe
Francis said:This is a prefect use case for the good old "reduce" function:
--BEGIN SNAP
a_lst = [None,0,0,1,1,1,2,2,3,3,3,2,2,2,4,4,4,5]
def straightforward_collapse(lst):
return reduce(lambda v,e: v[-1]!=e and v+[e] or v, lst[1:], [lst[0]])
Z powazaniemAlan McIntyre said:Hi all,
I have a list of items that has contiguous repetitions of values, but
the number and location of the repetitions is not important, so I just
need to strip them out. For example, if my original list is
[0,0,1,1,1,2,2,3,3,3,2,2,2,4,4,4,5], I want to end up with [0,1,2,3,2,4,5].
Here is the way I'm doing this now:
def straightforward_collapse(myList):
collapsed = [myList[0]]
for n in myList[1:]:
if n != collapsed[-1]:
collapsed.append(n)
return collapsed
Is there an elegant way to do this, or should I just stick with the code
above?p=[1,1,1,1,1,4,4,4,8,8,9]
filter(lambda y: y>0, map(lambda x,y: x==y and -1 or x,[0]+p,p+[0])) [1, 4, 8, 9]
Francis said:This is a prefect use case for the good old "reduce" function:
--BEGIN SNAP
a_lst = [None,0,0,1,1,1,2,2,3,3,3,2,2,2,4,4,4,5]
def straightforward_collapse(lst):
return reduce(lambda v,e: v[-1]!=e and v+[e] or v, lst[1:], [lst[0]])
reduce() magically increases the number of function calls by len(a_list).
There will be no good use cases for reduce() until Python can inline
functions.
Apodictically Yours
Peter
Francis said:Python documentation should say "There is no good use case for the reduce
function in Python and we don't know why we bother you offering it."
Francis said:I'm very sorry that there is no good use case for the "reduce" function in
Python, like Peter Otten pretends. That's an otherwise very useful tool for
many use cases. At least on paper.
Zut !
I'm very sorry that there is no good use case for the "reduce" function in
Python, like Peter Otten pretends. That's an otherwise very useful tool for
many use cases. At least on paper.
Python documentation should say "There is no good use case for the reduce
function in Python and we don't know why we bother you offering it."
Francis said:I'm very sorry that there is no good use case for the "reduce" function
in Python, like Peter Otten pretends. That's an otherwise very useful
tool for many use cases. At least on paper.
Clarity aside[1], can you give an example of where reduce is as
efficient as the eqivalent loop in Python?
Steve
[1] I generally find most reduce solutions much harder to read, but
we'll set aside my personal limitations for the moment.![]()
Francis said:Is there someone on this list using this tool and happy with it ? Or is my
mind too much targeted on FP paradigm and most of you really think that all
the functions that apply another function to each and every elements of a
list are bad (like "reduce", "map", "filter") ?
John said:For example, the fastest way
to get the factorial of a (small enough) number in pure python is
factorial = lambda n: reduce(operator.mul, range(1, n+1))
I am guessing you are joking, right?
I think Peter exaggerates when he
says that "there will be no good use cases for reduce"; it is very
useful, in writing very compact code when it does exactly what you
want (and you have to go through hoops to do it otherwise). It also
can be the fastest way to do something. For example, the fastest way
to get the factorial of a (small enough) number in pure python is
factorial = lambda n: reduce(operator.mul, range(1, n+1))
Francis said:Is there someone on this list using this tool and happy with it ? Or is
my mind too much targeted on FP paradigm and most of you really think
that all the functions that apply another function to each and every
elements of a list are bad (like "reduce", "map", "filter") ?
I know there are definitely proponents for map and filter, especially
for simple cases like:
map(int, lst)
filter(str.strip, lst)
Note that, unlike reduce, map and filter aren't really going to increase
the number of function calls. Consider the equivalent list comprehensions:
[int(x) for x in lst]
[x for x in lst if str.strip(x)] [1]
The list comprehensions also require the same number of function calls
in these cases. Of course, in cases where a function does not already
exist, map and filter will require more function calls. Compare:
map(lambda x: x**2 + 1, lst)
with
[x**2 + 1 for x in lst]
Where the LC allows you to essentially "inline" the function. (You can
dis.dis these to see the difference if you like.)
As far as my personal preferences go, while the simple cases of map and
filter (the ones using existing functions) are certainly easy enough for
me to read, for more complicated cases, I find things like:
[x**2 + 1 for x in lst]
[x for x in lst if (x**2 + 1) % 3 == 1]
much more readable than the corresponding:
map(lambda x: x**2 + 1, lst)
filter(lambda x: (x**2 + 1) % 3 == 1, lst)
especially since I avoid lambda usage, and would have to write these as:
def f1(x):
return x**2 + 1
map(f1, lst)
def f2(x):
return (x**2 + 1) % 3 == 1
map(f2, lst)
(I actually find the non-lambda code clearer, but still more complicated
than the list comprehensions.)
Given that I use list comprehensions for the complicated cases, I find
it to be more consistent if I use list comprehensions in all cases, so I
even tend to avoid the simple map and filter cases.
As far as reduce goes, I've never seen code that I thought was clearer
using reduce than using a for-loop. I have some experience with FP, and
I can certainly figure out what a given reduce call is doing given
enough time, but I can always understand the for-loop version much more
quickly.
Of course, YMMV.
STeVe
[1] While it's not technically equivalent, this would almost certainly
be written as:
[x for x in lst if x.strip()]
which in fact takes better advantage of Python's duck-typing -- it will
work for unicode objects too.
Francis said:Le lundi 7 Février 2005 20:30, Steven Bethard a écrit :
Why avoid "lambda" usage ? You find them too difficult to read (I mean in
general) ?
John said:I am guessing you are joking, right? I think Peter exaggerates when he
says that "there will be no good use cases for reduce"; it is very
useful, in writing very compact code when it does exactly what you
want (and you have to go through hoops to do it otherwise). It also
can be the fastest way to do something. For example, the fastest way
to get the factorial of a (small enough) number in pure python is
factorial = lambda n: reduce(operator.mul, range(1, n+1))
John said:For example, the fastest way
to get the factorial of a (small enough) number in pure python is
factorial = lambda n: reduce(operator.mul, range(1, n+1))
I see that you are seduced by the beauty of the expression. Otherwise, if
you would really care for speed:
[...]
Yup, basically a readability thing. I also tend to find that if I
actually declare the function, I can often find a way to refactor things
to make that function useful in more than one place.
Additionally, 'lambda' is on Guido's regrets list, so I'm avoiding it's
use in case it gets yanked for Python 3.0. I think most code can be
written now without it, and in most cases code so written is clearer.
Probably worth looking at is a thread I started that went through some
stdlib uses of lambda and how they could be rewritten:
http://mail.python.org/pipermail/python-list/2004-December/257990.html
Many were rewritable with def statements, list comprehensions, the
operator module functions, or unbound or bound methods.
Steve
Francis said:I see. I personnaly use them frequently to bind an argument of a function with
some fixed value. Modifying one of the example in
http://mail.python.org/pipermail/python-list/2004-December/257990.html
I frequently have something like :
SimpleXMLRPCServer.py: server.register_1arg-place_function(lambda x: x+2,
'add2')
John said:John said:For example, the fastest way
to get the factorial of a (small enough) number in pure python is
factorial = lambda n: reduce(operator.mul, range(1, n+1))
I see that you are seduced by the beauty of the expression. Otherwise, if
you would really care for speed:
[...]
that's cheating: you moved the calculation into the setup. You aren't
timing what you say you are.
Francis said:I see. I personnaly use them frequently to bind an argument of a function
with some fixed value. Modifying one of the example in
http://mail.python.org/pipermail/python-list/2004-December/257990.html
I frequently have something like :
SimpleXMLRPCServer.py: server.register_1arg-place_function(lambda x:
x+2, 'add2')
PEP 309 has already been accepted, so I assume it will appear in Python
2.5:
http://www.python.org/peps/pep-0309.html
Your code could be written as:
server.register_1arg-place_function(partial(operator.add, 2))
If your task is actually what you describe above -- "to bind an argument
of a function with some fixed value"[1] -- then in general, you should
be able to write this as[2]:
function_with_fixed_value = partial(function, fixed_value)
Steve
[1] As opposed to binding a name to be used in an _expression_ as you do
in your example.
[2] The partial function can also be used to fix multiple argument
values and keyword argument values, if that's necessary for your purposes.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.