0

My input looks as below

 txt = ['or', [{'fact': 'name', 'operator': 'equals', 'criteria': 'Network'}]]

code functionaltiy replace any occurence of equals in the input with greater. Note it can be multiple occurence of the list

Expected output :

Output: ['or', [{'fact': 'name','operator': 'greater', 'criteria': 'Network'}]]

Tried with the below code :

result = ' '.join(map(str, txt)).replace("equals", "greater")

which gives or [{'fact': 'name', 'operator': 'greater', 'criteria': 'Network'}] . How do I join back to the get original list

4
  • That's not the right method. That gives you a string, not a list. Do you have several of these in different forms? The easy way is if txt[1][0]['operator'] == 'equals': / txt[1][0]['operator'] = 'greater'. Commented Jun 16, 2021 at 6:04
  • 1
    "My input string looks as below" - that isn't a string. Commented Jun 16, 2021 at 6:04
  • @TimRoberts Yes it can be multiple forms Commented Jun 16, 2021 at 6:07
  • @KarlKnechtel Yes, it is. He converted the whole thing to a string and did a string replace. It's a string that looks like a list/dict. Commented Jun 16, 2021 at 6:54

2 Answers 2

1

You can try something like this:

eq_txt = ['or', [{'fact': 'name', 'operator': 'equals', 'criteria': 'Network'}]]
gt_txt = [[{k: ('greater' if v == 'equals' else v) for k, v in d.items()} if isinstance(d, dict) else d for d in e] if isinstance(e, list) else e for e in eq_txt]

print(gt_txt)
# Output: ['or', [{'fact': 'name', 'operator': 'greater', 'criteria': 'Network'}]]

Weird? Let's break it down:

gt_txt = [A1 if isinstance(e, list) else e for e in eq_txt]
A1 := [A2 if isinstance(d, dict) else d for d in e]
A2 := {k: A3 for k, v in d.items()}
A3 := 'greater' if v == 'equals' else v

So, for each element in the original list, check if this element a list. If it is (let's call it e), return A1. If it's not, return the element itself.

If e is a list, for each element in e, check if this element is a dict. If it is (let's call it d), return A2. If it's not, return the element itself.

If d is a dict, for each key-value pair in d, return the key mapped to "greater" if the previous value was "equal" else to the previous value.


If you want to replace every occurence of "greater" inside the original list, you can use the json module only if your original list contains types such as strings, numbers, lists and dicts:

import json

eq_txt = ['or', [{'fact': 'name', 'operator': 'equals', 'criteria': 'Network'}]]
gt_txt = json.loads(json.dumps(eq_txt).replace('equals', 'greater'))

print(gt_txt)
# Output: ['or', [{'fact': 'name', 'operator': 'greater', 'criteria': 'Network'}]]
Sign up to request clarification or add additional context in comments.

Comments

1

You can always do things like this recursively. Here the base case is when you pass it neither a dict or list, it just replaces based on the ternary. Otherwise it passes the items from the collection back in. This has the advantage of working for arbitrary nesting and formats:

l = ['or', [{'fact': 'name', 'operator': 'equals', 'criteria': 'Network'}]]

def replace_str(obj, t, r):
    if isinstance(obj, list):
        return [replace_str(o, t, r) for o in obj]
    elif isinstance(obj, dict):
        return {replace_str(k, t, r): replace_str(v, t, r) for k, v in obj.items() }
    return r if obj == t else obj

replace_str(l, 'equals', 'greater')
# ['or', [{'fact': 'name', 'operator': 'greater', 'criteria': 'Network'}]]

# nested  + (won't replace not-equals):
l = {"a":{"b": [1, {"g":{"h":"equals"}}, 3, "not-equals"]}, "c":"equals"}
replace_str(l, 'equals', 'greater')
# {'a': {'b': [1, {'g': {'h': 'greater'}}, 3, 'not-equals']}, 'c': 'greater'}

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.