Tytire Recubans
Tytire Recubans

Reputation: 997

reduce functions on a dictionary python

This might be somehow of a trivial question, but I have a dictionary on which I would like to apply some 10 functions to modify its content.

I think this would be a good case for reduce but I cannot seem to make it work.

Here's an example

from datetime import datetime
import re
from functools import reduce 


d_ = {
      "dob_partial": "20120314", 
      "service_address_country":"Uni44ed Kind-om"
     }

What I would like as a results:

d_ = {
      "dob_partial": "20120314",
      "dob": datetime.datetime(2012, 3, 14, 0, 0)
      "service_address_country":"Uni44ed Kind-om"
      "service_address_country_clean":"Unied Kindom"
     }

Here's the replicable code:

# pre-processing functions

def clean_address_country_code(d):

    key = 'service_address_country'
    d[key + 'clean'] = re.sub('[^a-zA-Z ]+', '', d[key])

    return d

def add_datestr_to_date(d):

    key = 'dob_partial'
    d['dob'] = datetime.strptime(d.get(key), '%Y%m%d')

    return d

# pipeline function to apply all preprocessing functions

def apply_all_preprocessing(fns, dic):

    reduce(lambda fn, d=dic: fn(dic), fns)

    return dic

fns = [add_datestr_to_date, clean_address_country_code]

apply_all_preprocessing(fns, d_)

Which works only partially (it applies only the first function in the list fns):

>>> print(apply_all_preprocessing(fns, d_))

{'dob_partial': '20120314', 'service_address_country': 'Uni44ed K-?indom', 'dob': datetime.datetime(2012, 3, 14, 0, 0)}

Upvotes: 0

Views: 122

Answers (2)

Nick Lee
Nick Lee

Reputation: 5949

The order of your lambda arguments are swapped. It should be lambda value, element: .... In your case:

def apply_all_preprocessing(fns, dic):
    return reduce(lambda d,f: f(d), fns, dic)

Supply the initial dictionary as the last argument to reduce().

Upvotes: 1

Ma0
Ma0

Reputation: 15204

I am going to simplify your example to try to answer what I think you are asking.

d_ = {"A": -1, "B": 2}

def f1(n):
    return n*2

def f2(n):
    return n**2

...

So we have a dictionary d_ and a bunch of functions (fi) that we want to apply to its values; maybe all of them sequentially, maybe only some of them in whatever order. Well, how about this:

def apply_all_preprocessing(fns, dic):
    for f in fns:
      dic = {k: f(v) for k, v in dic.items()}
    return dic

fns = [f1, f2]

res = apply_all_preprocessing(fns, d_)

print(res)   # -> {'A': 4, 'B': 16}
#                       |        |= f2(f1(2)) = f2(2 * 2) = 4^2 = 16
#                       |= f2(f1(-1)) = f2(-1 * 2) = (-2)^2 = 4

Upvotes: 1

Related Questions