Replace a string to a value in dict using Python

Suppose I have a list of dictionary

    [{'TELEPHONE': '111', 'STATUS': 'BUSY'}, {'TELEPHONE': '122', 'STATUS': 'BUSY'}, 
    {'TELEPHONE': '133', 'STATUS': 'FREE'}]

and I have a sentence "PHONE is STATUS". I want to replace the keyword from the sentence to the values in the dictionary. So the output should be

111 is BUSY 122 is BUSY 133 is FREE

Since STATUS matches the key in the dictionary, so I can use re to replace it,

    pattern = re.compile(r'\b(' + '|'.join(val.keys()) + r')\b')
    result = pattern.sub(lambda x: val[x.group()], text)

but the pattern PHONE is different to the key TELEPHONE in the dictionary, is there a similar way to do such replacement? I don't want to change the keys in the dictionary. Can I do something like "if I meet "PHONE", then I retrieve using the key "TELEPHONE" in the dict?"

4 answers

  • answered 2017-11-12 20:26 Serg Anuke

    Try this:

    l = [{'TELEPHONE': '111', 'STATUS': 'BUSY'}, {'TELEPHONE': '122', 'STATUS': 'BUSY'}, {'TELEPHONE': '133', 'STATUS': 'FREE'}]
    print("".join(["{} is {}".format(
        i['TELEPHONE'], i['status']) for i in l]))
    

  • answered 2017-11-12 20:31 Ajax1234

    You can try this:

    import re
    sentence = "PHONE is STATUS"
    keys = re.findall('[A-Z]+', sentence)
    s = [{'TELEPHONE': '111', 'STATUS': 'BUSY'}, {'TELEPHONE': '122', 'STATUS': 'BUSY'}, {'TELEPHONE': '133', 'STATUS': 'FREE'}]
    final_data = ' '.join([' is '.join([[b for a, b in i.items() if a.endswith(keys[0])][0], i[keys[-1]]]) for i in s])
    

    Output:

    '111 is BUSY 122 is BUSY 133 is FREE'
    

  • answered 2017-11-12 20:34 Jean-François Fabre

    I would create a fallback key dictionary, so if PHONE isn't found, it looks for a corresponding key in the dict that we cannot change, using chained get calls with default values. I'd apply that on each word & rebuild the sentence

    dl = [{'TELEPHONE': '111', 'STATUS': 'BUSY'}, {'TELEPHONE': '122', 'STATUS': 'BUSY'},
        {'TELEPHONE': '133', 'STATUS': 'FREE'}]
    
    # synonyms dict, you can add as many as you want
    mk = {"PHONE" : "TELEPHONE", "STATE" : "STATUS"}
    
    
    for d in dl:
        print(" ".join(d.get(w,d.get(mk.get(w),w)) for w in "PHONE is STATUS".split()))
    

    result:

    111 is BUSY
    122 is BUSY
    133 is FREE
    

    the advantage of this method is that there's no linear lookup. The problem is that both get are performed, which can be solved with a or short circuit:

    print(" ".join(d.get(w) or d.get(mk.get(w),w) for w in "PHONE is STATUS".split()))
    

    now if w is in d, it doesn't evaluate the second part of the expression.

  • answered 2017-11-12 20:36 soundstripe

    Hard to tell what you're trying to accomplish but I think you have a phone list and are getting log messages to update their status. Try this:

    import re
    
    status_update = '111 is BUSY'
    status_re = re.compile('(\d+) is ([A-Z]+)')
    
    phone, new_status = status_re.match(status_update).groups()
    found = False
    for val in phone_list:
        if phone == val['TELEPHONE']:
            val['STATUS'] = new_status
            found = True
    if not Found:
        print('phone not found')
    else:
        print('phone status updated')