Reputation: 15
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
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
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
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
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