0

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'
2
  • I am not sure how lambda function fits here. bb() is not a lambda function. Commented Feb 22, 2018 at 21:25
  • 1
    what about a for loop? Commented Feb 22, 2018 at 21:28

4 Answers 4

2

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)
Sign up to request clarification or add additional context in comments.

4 Comments

it seems OP is asking a function to query the cat field of some prop. it does not do that
Ok this is more like it. I knew it was something missing indeed. Upvoted.
like this and another one, learnt a lot from both, thank you. though dont know which I should accept :)
@MeOkey accept this one here. It makes more sense in your use-case. If you wanted to find multiple entries mine would work.
2

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

2 Comments

Thank you. I'm trying to learn lambda. it's just an exercise and I got your point that function should be used in such case.
@MeOkey then jpp 's answer should be proper for you.
2

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'

4 Comments

any way to get the string instead of list?
@MeOkey In this case you can use str.join()
@MeOkey You can use [0] too after. But this is fail safe. str.join() works for list of any length.
like this and another one, learnt a lot from both, thank you. though dont know which I should accept :)
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.