Me Okey
Me Okey

Reputation: 15

python: converting List Comprehension to lambda function?

I have a list below, and I'm trying to have a lambda function to retrieve 'cat' value from the list when 'prop' equals to a given string.

a=[{'prop':'ABC','cat':'ABC Dir'}, {'prop':'DEF','cat':'DEF Dir'}, ...]

I have successfully got a List Comprehension, which gives me expected 'ABC Dir' if I feed in 'ABC', but I failed to convert it to a lambda function if possible. Advise is appreciated.

>>> aa=[x['cat'] for x in a if x['prop'] == 'ABC']
>>> aa
['ABC Dir']

expected result:

>>>bb('ABC')
'ABC Dir'
>>>bb('DEF')
'DEF Dir'

Upvotes: 0

Views: 1879

Answers (4)

Anton vBR
Anton vBR

Reputation: 18906

Using list comprehensions (however generators as kindall has proposed is the most pythonic way):

a=[{'prop':'ABC','cat':'ABC Dir'}, {'prop':'DEF','cat':'DEF Dir'}]

bb = lambda prop: ' '.join([val['cat'] for val in a if val['prop'] == prop])

bb('ABC')

Would give you a string with all the matches:

'ABC Dir'

And here is another one that will join the matches with a blank space and if you want to pass an array too:

f = lambda prop, d: ' '.join([val['cat'] for val in d if val['prop'] == prop])

f('ABC',a)

Returns:

'ABC Dir'

Upvotes: 2

jpp
jpp

Reputation: 164613

You may have to combine filter and map for a truly functional approach.

a = [{'prop':'ABC','cat':'ABC Dir'}, {'prop':'DEF','cat':'DEF Dir'}]

def bifilter(LoD, prop):
    return map(lambda x: x['cat'], filter(lambda d: d['prop'] == prop, LoD))

list(bifilter(a, 'ABC'))  # ['ABC Dir']

My advice would be to go with a list comprehension.

Upvotes: 0

kindall
kindall

Reputation: 184071

If you wanted to write a function that performed that list comprehension, it would accept the original list as a parameter, along with the value to test against, and return the result of the list comprehension, like so:

def getcats(a, value):
    return [x['cat'] for x in a if x['prop'] == value]

This is easily converted to an anonymous function (lambda) since it returns the result of a single expression.

lambda a, value: [x['cat'] for x in a if x['prop'] == value]

If you want just the first value, you can use next() with a generator expression. That way, it stops when it finds the first value.

lambda a, value: next(x['cat'] for x in a if x['prop'] == value)

Of course, there might not be any matching values. In that case, you can add the optional second parameter of next() to return None in that instance.

lambda a, value: next((x['cat'] for x in a if x['prop'] == value), None)

Upvotes: 2

Jason Hu
Jason Hu

Reputation: 6333

I will take it as you don't quite get the terminologies in python. Lambda is a key word in python. If you want to define a function, just say define a function. In fact, you don't use lambda to define a named function at all.

Following code should do what you are asking for:

def bb(x):
    for i in a:
        if i['prop'] == x:
            return i['cat']
    else:
        return None

It's in the style guide, PEP8, that you shouldn't define a named function using lambda: https://www.python.org/dev/peps/pep-0008/

Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.

Yes:

def f(x): return 2*x

No:

f = lambda x: 2*x

Upvotes: 2

Related Questions