Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python : can reduce be translated into list comprehensions like map, lambda and filter?

When programming in python, I now avoid map, lambda and filter by using list comprehensions because it is easier to read and faster in execution. But can reduce be replaced as well?

E.g. an object has an operator union() that works on another object, a1.union(a2), and gives a 3rd object of same type.

I have a list of objects:

L = [a1, a2, a3, ...] 

How to have the union() of all these objects with list comprehensions, the equivalent of:

result = reduce(lambda a, b :a.union(b), L[1:], L[0]) 
like image 549
Eric H. Avatar asked Jun 25 '14 13:06

Eric H.


People also ask

How do you reduce a list in Python?

Python offers a function called reduce() that allows you to reduce a list in a more concise way. The reduce() function applies the fn function of two arguments cumulatively to the items of the list, from left to right, to reduce the list into a single value.

What is filter () map () and reduce ()?

Map, Filter, and Reduce are paradigms of functional programming. They allow the programmer (you) to write simpler, shorter code, without neccessarily needing to bother about intricacies like loops and branching.

What is map filter and lambda in Python?

The map() function in Python takes in a function and a list as an argument. The function is called with a lambda function and a list and a new list is returned which contains all the lambda modified items returned by that function for each item.


2 Answers

It is no secret that reduce is not among the favored functions of the Pythonistas.

Generically, reduce is a left fold on a list

It is conceptually easy to write a fold in Python that will fold left or right on a iterable:

def fold(func, iterable, initial=None, reverse=False):     x=initial     if reverse:         iterable=reversed(iterable)     for e in iterable:         x=func(x,e) if x is not None else e     return x 

Without some atrocious hack, this cannot be replicated in a comprehension because there is not accumulator type function in a comprehension.

Just use reduce -- or write one that makes more sense to you.

like image 144
dawg Avatar answered Sep 29 '22 07:09

dawg


Since a list comprehension definitionally generates another list, you can't use it to generate a single value. The aren't for that. (Well... there is this nasty trick that uses a leaked implementation detail in old versions of python that can do it. I'm not even going to copy the example code here. Don't do this.)

If you're worried about the stylistic aspects of reduce() and its ilk, don't be. Name your reductions and you'll be fine. So while:

all_union = reduce(lambda a, b: a.union(b), L[1:], L[0]) 

isn't great, this:

from functools import reduce  def full_union(input):     """ Compute the union of a list of sets """     return reduce(set.union, input[1:], input[0])  result = full_union(L) 

is pretty clear.

If you're worried about speed, check out the toolz and cytoolz packages, which are 'fast' and 'insanely fast,' respectively. On large datasets, they'll often let you avoid processing your data more than once or loading the whole set in memory at once, in contrast to list comprehensions.

like image 31
Nate Avatar answered Sep 29 '22 08:09

Nate