python_user
python_user

Reputation: 7123

Pattern matching find pattern anywhere in list

I have the following dictionary and I would like to get the value of "msg", if the "status" is "progress". The status "progress" or the key "msg" may or may not be in the dictionary, which is why I thought of using pattern matching to see if I can get what I want.

My attempt

my_dict = {
    "outer": [
        {"status": "to do", "desc": [{"msg": "foo"}]},
        {"status": "progress", "desc": [{"msg": "bar"}]},
        {"status": "done", "desc": [{"msg": "baz"}]},
    ]
}

match my_dict:
    case {'outer': [{'status': 'progress', 'desc': [{'msg': x}]}]}:
        print(x)

I am looking for something like case {'outer': [*_, {'status': 'progress', 'desc': [{'msg': x}]}, *_]}: but that does not work SyntaxError: multiple starred names in sequence pattern

Output I want (using pattern matching)

bar

I can get what I want with something like the following, but there are some checks I need to do make sure the key exists.

for i in my_dict['outer']: # check every status
    if i['status'] == 'progress': # check if the status is "progress"
        if 'desc' in i:
            for j in i['desc']: # loop the values of "desc"
                if 'msg' in j: # if the msg is there get the value
                    x = j['msg']

I want to know if there is a way to solve this using pattern matching, just out of curiosity.

Upvotes: 0

Views: 260

Answers (2)

Ajax1234
Ajax1234

Reputation: 71471

If it is guaranteed that the value progress will only occur once in my_dict['outer'], then you can pre-filter the list of items before match:

my_dict = {'outer': [{'status': 'to do', 'desc': [{'msg': 'foo'}]}, {'status': 'progress', 'desc': [{'msg': 'bar'}]}, {'status': 'done', 'desc': [{'msg': 'baz'}]}]}
match [i for i in my_dict['outer'] if i['status'] == 'progress']:
   case [{'status': _, 'desc': [{'msg': msg}]}]:
      print(msg)

Output:

'bar'

Upvotes: 1

Sayandip Dutta
Sayandip Dutta

Reputation: 15872

I guess you could do the following:

for info in my_dict["outer"]:
    match info:
        case {"status": "progress", "desc": [{"msg": msg}]}:
            print(msg)
            break
else:
    print("No Match")

Upvotes: 1

Related Questions