Do anyone here have any useful code which uses reduce() function of python? Is there any code other than the usual + and * that we see in the examples?
Refer Fate of reduce() in Python 3000 by GvR
Do anyone here have any useful code which uses reduce() function of python? Is there any code other than the usual + and * that we see in the examples?
Refer Fate of reduce() in Python 3000 by GvR
Not sure if this is what you are after but you can search source code on Google.
Follow the link for a search on 'function:reduce() lang:python' on Google Code search
At first glance the following projects use reduce()
etc. etc. but then these are hardly surprising since they are huge projects.
The functionality of reduce can be done using function recursion which I guess Guido thought was more explicit.
I have an old Python implementation of pipegrep that uses reduce and the glob module to build a list of files to process:
files = []
files.extend(reduce(lambda x, y: x + y, map(glob.glob, args)))
I found it handy at the time, but it's really not necessary, as something similar is just as good, and probably more readable
files = []
for f in args:
files.extend(glob.glob(f))
@Blair Conrad: You could also implement your glob/reduce using sum, like so:
files = sum([glob.glob(f) for f in args], [])
This is less verbose than either of your two examples, is perfectly Pythonic, and is still only one line of code.
So to answer the original question, I personally try to avoid using reduce because it's never really necessary and I find it to be less clear than other approaches. However, some people get used to reduce and come to prefer it to list comprehensions (especially Haskell programmers). But if you're not already thinking about a problem in terms of reduce, you probably don't need to worry about using it.
@Eli: thanks! I overlooked sum, probably mostly because I wrote my pipegrep off 1.5.2, and I'm not particularly good at checking out new language features (I'm lazy and copy my old code - I know, I'm hardly the only one). I can't wait to go and try out my new idiom!
After grepping my code, it seems the only thing I've used reduce for is calculating the factorial:
reduce(operator.mul, xrange(1, x+1) or (1,))
The usage of reduce
that I found in my code involved the situation where I had some class structure for logic expression and I needed to convert a list of these expression objects to a conjunction of the expressions. I already had a function make_and
to create a conjunction given two expressions, so I wrote reduce(make_and,l)
. (I knew the list wasn't empty; otherwise it would have been something like reduce(make_and,l,make_true)
.)
This is exactly the reason that (some) functional programmers like reduce
(or fold functions, as such functions are typically called). There are often already many binary functions like +
, *
, min
, max
, concatenation and, in my case, make_and
and make_or
. Having a reduce
makes it trivial to lift these operations to lists (or trees or whatever you got, for fold functions in general).
Of course, if certain instantiations (such as sum
) are often used, then you don't want to keep writing reduce
. However, instead of defining the sum
with some for-loop, you can just as easily define it with reduce
.
Readability, as mentioned by others, is indeed an issue. You could argue, however, that only reason why people find reduce
less "clear" is because it is not a function that many people know and/or use.
The other uses I've found for it besides + and * were with and and or, but now we have any
and all
to replace those cases.
foldl
and foldr
do come up in Scheme a lot...
Here's some cute usages:
Flatten a list
Goal: turn [[1, 2, 3], [4, 5], [6, 7, 8]]
into [1, 2, 3, 4, 5, 6, 7, 8]
.
reduce(list.__add__, [[1, 2, 3], [4, 5], [6, 7, 8]], [])
List of digits to a number
Goal: turn [1, 2, 3, 4, 5, 6, 7, 8]
into 12345678
.
Ugly, slow way:
int("".join(map(str, [1,2,3,4,5,6,7,8])))
Pretty reduce
way:
reduce(lambda a,d: 10*a+d, [1,2,3,4,5,6,7,8], 0)
reduce()
can be used to find Least common multiple for 3 or more numbers:
def lcmm(*args):
return reduce(lcm, args)
>>> lcmm(100, 23, 98)
112700
>>> lcmm(*range(1, 20))
232792560
reduce()
could be used to resolve dotted names (where eval()
is too unsafe to use):
>>> import __main__
>>> reduce(getattr, "os.path.abspath".split('.'), __main__)
<function abspath at 0x009AB530>
I'm writing a compose function for a language, so I construct the composed function using reduce along with my apply operator.
In a nutshell, compose takes a list of functions to compose into a single function. If I have a complex operation that is applied in stages, I want to put it all together like so:
complexop = compose(stage4, stage3, stage2, stage1)
This way, I can then apply it to an expression like so:
complexop(expression)
And I want it to be equivalent to:
stage4(stage3(stage2(stage1(expression))))
Now, to build my internal objects, I want it to say:
Lambda([Symbol('x')], Apply(stage4, Apply(stage3, Apply(stage2, Apply(stage1, Symbol('x'))))))
(The Lambda class builds a user-defined function, and Apply builds a function application.)
Now, reduce, unfortunately, folds the wrong way, so I wound up using, roughly:
reduce(lambda x,y: Apply(y, x), reversed(args + [Symbol('x')]))
To figure out what reduce produces, try these in the REPL:
reduce(lambda x, y: (x, y), range(1, 11))
reduce(lambda x, y: (y, x), reversed(range(1, 11)))
Find intersection of N given list:
input_list = [[1,2,3,4,5],[2,3,4,5,6],[3,4,5,6,7]]
result = reduce(set.intersection,map(set,input_list))
returns:
result = set([3, 4, 5])