简体   繁体   中英

How to create function that accepts lambda expression in python?

How do I create a function which accepts lambda expression like,

# dummy data
data = [{"dim":["abc","sdc"], "mea":[23,23,134]},{"dim":["jgdf","dfc"], "mea":[34,245,2345]}....]

"""
also note that data may be change, [{"x":[{"dim":["abc","sdc"], "mea":[23,23,134]},{"dim":["jgdf","dfc"], "mea":[34,245,2345]}....], "y":.....},...]

but data structure (dictionary) for keys "dim" & "mea" will remain same.
"""  

def function(data,key=lambda x: x):
    """
    Logic:

    sum1 = sum(i["mea"][0] for i in data)

    return [[data[i]["dim"],data[i]["mea"][0]] for i in range(len(data)) if data[i]["mea"][0] * len(data) / sum1 > 1]

    now i want equivalent lambda function that works for any data 
    constraint is that structure before "dim" & "mea" will change.
    """

how do i create that type of function?

Any help that is appreciated.

A lambda can be treated like any regular variable that is callable:

def function(data, f):
   return f(data)

In your case to create a max function:

def max(data, key = lambda x: x):
  m = lambda a,b: a if key(a) > key(b) else b
  return reduce(m, data)

or more verbose:

def max(data, key = lambda x: x):
  max_ = data[0]
  for d in data:
    if key(d) > key(max_): max_ = d
  return max_

How to optimize this to avoid calling key too often is left as an exercise for the reader.

More Examples

Max:

>>> reduce(lambda a,b: a if a['hi'] > b['hi'] else b, [{"hi":0},{"hi":-1},{"hi":9}])
{'hi': 9}

Sum:

>>> reduce(lambda a,b: {"hi":a["hi"]+b["hi"]}, [{"hi":1},{"hi":2},{"hi":3}])
{'hi': 6}

More generic:

>>> def generic(data, f, key = lambda x: x, cons = lambda x: x):
...    return reduce(lambda a,b: cons(f(key(a),key(b))), data)
... 
>>> generic([{"hi":1},{"hi":2},{"hi":3}], lambda a,b: a*b, key = lambda x: x["hi"], cons = lambda x: {"hi":x})
{'hi': 6}

>>> def generic_select(data, f, key = lambda x: x):
...   return reduce(lambda a,b: a if f(key(a), key(b)) else b, data)
... 
>>> generic_select([{"hi":1,"a":"b"},{"hi":0,"a":"c"}], lambda a,b: True if a < b else False, key = lambda x: x["hi"])
{'a': 'c', 'hi': 0}

It depends on what you actually want to do. If you want a reduction that applies a bin op use generic if you want a reduction that decides between taking a,b use generic_select .

Reduce

Reduce isn't available in python3 without an import but you can import it from the functools package. It's a very common and simple pattern:

>>> def reduce_(data, f):
...   r = data[0]
...   for r_ in data[1:]:
...     r = f(r, r_)
...   return r
... 
>>> reduce_([1,2,3], lambda a,b: a+b)
6
>>> reduce_([1,2,3], lambda a,b: a if a > b else b)
3

Sometimes it may be necessary to specify an initial value instead of using data[0] :

>>> def reduce1(data, init, f):
...   r = init
...   for r_ in data:
...     r = f(r, r_)
...   return r
... 
>>> reduce1([1,2,3], [], lambda a,b: [b]+a)
[3, 2, 1]

A reduction of lambda a,b: [b]+a reverses a list. reduce means to reduce a list of values to a single value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM