Explain this python lambda

238 Views Asked by At

I am implementing a monthly calendar in django and used some code I found online. Within the code there is a lambda function that I need to tune for my specific use.

def group_by_day(self, event):
        field = lambda event: event.start.day
        return dict(
            [(day, list(items)) for day , items in groupby(event, field)]
        )

From what I read online:

group_by_day() builds a dictionary with the day of the month as key and any workouts for that day as its value (http://uggedal.com/journal/creating-a-flexible-monthly-calendar-in-django/)

Im quite new to python and having problem figuring out how its actually doing its magic. I do understand that it uses the event.start.day to assign it to a day and month. Is it doing this with recursion?

I'm trying to tune the function so it would support recurring/multi-day events.

Thanks

3

There are 3 best solutions below

1
On BEST ANSWER

All the lambda does is return the day portion of the event start date; lambda objects are just functions. The real magic is in the itertools.groupby() function, which produces groups based on that return value. Each time the value changes from one event to the next, you get a new group.

Depending on how your multiday / recurrence is implemented, it probably is not going to be easy to adapt this directly to your case. You'd have to switch to a loop with a dictionary instead.

Here is an equivalent function using just a loop, which will be easier to adapt:

def group_by_day(self, event):
    result = {}
    for e in event:
        day = event.start.day
        result.setdefault(day, []).append(event)
    return result

This is not dependent on the order of the events as it'll just group every date by the day regardless of where it appears in the sequence. This should let you add an event to more than one day.

0
On

Lambda functions are like regular functions. For example:

f = lambda x:x**2

Is equivelent to:

def f(x):
    return x**2

So, in your case, for field(event), return event.start.day

0
On

There are three separate bits of magic: the lambda, the list comprehension, and the groupby function.

The statement lambda event: event.start.day is equivalent to:

def f(event):
  return event.start.day

The groupby function presumably takes an event and a field and returns some sort of list of two-element lists (or tuples).

The list comprehension [(day, list(items)) for day , items in groupby(event, field)] is equivalent to:

result = []
for day, items in groupby(event, field):
    result.append( (day, list(items)) )

And then the dict call takes that list of tuples and turns it into a dict of day:list(items) pairs.