trying to replace all elements named 'number' to 'numbr' in the data list but doesn't get it working.
Edit: So each key number should be renamed to numbr. Values stay as they are.
What am I doing wrong?
Thank you for your help!
data = [{'address': {
'city': 'city A',
'company_name': 'company A'},
'amount': 998,
'items': [{'description': 'desc A1','number': 'number A1'}],
'number': 'number of A',
'service_date': {
'type': 'DEFAULT',
'date': '2015-11-18'},
'vat_option': 123},
{'address': {
'city': 'city B',
'company_name': 'company B'},
'amount': 222,
'items': [{'description': 'desc B1','number': 'number B1'},
{'description': 'desc B2','number': 'number B2'}],
'number': 'number of B',
'service_date': {
'type': 'DEFAULT',
'date': '2015-11-18'},
'vat_option': 456}
]
def replace(l, X, Y):
for i,v in enumerate(l):
if v == X:
l.pop(i)
l.insert(i, Y)
replace(data, 'number', 'numbr')
print data
-
1it should rename only keys? Post the expected resultRomanPerekhrest– RomanPerekhrest2017年10月13日 16:32:24 +00:00Commented Oct 13, 2017 at 16:32
-
This is the result - as you can see, no change: [{'vat_option': 123, 'items': [{'description': 'desc A1', 'number': 'number A1'}], 'number': 'number of A', 'amount': 998, 'address': {'city': 'city A', 'company_name': 'company A'}, 'service_date': {'date': '2015年11月18日', 'type': 'DEFAULT'}}, {'vat_option': 456, 'items': [{'description': 'desc B1', 'number': 'number B1'}, {'description': 'desc B2', 'number': 'number B2'}], 'number': 'number of B', 'amount': 222, 'address': {'city': 'city B', 'company_name': 'company B'}, 'service_date': {'date': '2015年11月18日', 'type': 'DEFAULT'}}]thowi– thowi2017年10月13日 17:55:31 +00:00Commented Oct 13, 2017 at 17:55
-
I've asked for the expected result, not the actualRomanPerekhrest– RomanPerekhrest2017年10月13日 17:57:06 +00:00Commented Oct 13, 2017 at 17:57
-
Sorry. Expected result is: [{'vat_option': 123, 'items': [{'description': 'desc A1', 'numbr': 'number A1'}], 'numbr': 'number of A', 'amount': 998, 'address': {'city': 'city A', 'company_name': 'company A'}, 'service_date': {'date': '2015年11月18日', 'type': 'DEFAULT'}}, {'vat_option': 456, 'items': [{'description': 'desc B1', 'numbr': 'number B1'}, {'description': 'desc B2', 'numbr': 'number B2'}], 'numbr': 'number of B', 'amount': 222, 'address': {'city': 'city B', 'company_name': 'company B'}, 'service_date': {'date': '2015年11月18日', 'type': 'DEFAULT'}}]thowi– thowi2017年10月13日 18:00:22 +00:00Commented Oct 13, 2017 at 18:00
-
So each key number -> numbr. Values stay as they are.thowi– thowi2017年10月13日 18:00:41 +00:00Commented Oct 13, 2017 at 18:00
3 Answers 3
The following is a recursive replace implementation that replaces p1 by p2 in any string it encounters in the s object, recursing through lists, sets, tuples, dicts (both keys and values):
def nested_replace(s, p1, p2):
if isinstance(s, basestring): # Python2
# if isinstance(s, (str, bytes)): # Python3
return s.replace(p1, p2)
if isinstance(s, (list, tuple, set)):
return type(s)(nested_replace(x, p1, p2) for x in s)
if isinstance(s, dict):
return {nested_replace(k, p1, p2): nested_replace(v, p1, p2) for k, v in s.items()}
return s
>>> from pprint import pprint
>>> pprint(nested_replace(data, 'number', 'numbr'))
[{'address': {'city': 'city A', 'company_name': 'company A'},
'amount': 998,
'items': [{'description': 'desc A1', 'numbr': 'numbr A1'}],
'numbr': 'numbr of A',
'service_date': {'date': '2015-11-18', 'type': 'DEFAULT'},
'vat_option': 123},
{'address': {'city': 'city B', 'company_name': 'company B'},
'amount': 222,
'items': [{'description': 'desc B1', 'numbr': 'numbr B1'},
{'description': 'desc B2', 'numbr': 'numbr B2'}],
'numbr': 'numbr of B',
'service_date': {'date': '2015-11-18', 'type': 'DEFAULT'},
'vat_option': 456}]
answered Oct 13, 2017 at 17:01
user2390182
73.7k6 gold badges71 silver badges95 bronze badges
Sign up to request clarification or add additional context in comments.
3 Comments
thowi
Thank you!!! That's a good start because it works fine! Awesome :) Is there a chance to only replace the keys? Current result is: 'numbr': 'numbr of B', it would be better to have it like: 'numbr': 'number of B',
user2390182
Sure, remove the block dealing with lists and stuff. And in the dict block, replace
nested_replace(v, p1, p2) by a simple v. You will lose the keys of nested dicts though...thowi
Hey, sorry to bother you again - can you please take a look here? I think I got you wrong, because replacing is not working :( def nested_replace(s, p1, p2): if isinstance(s, basestring): # Python2 return s.replace(p1, p2) # if isinstance(s, (list, tuple, set)): # return type(s)(nested_replace(x, p1, p2) for x in s) if isinstance(s, dict): return {nested_replace(k, p1, p2): v for k, v in s.items()} return s
eval function is anti pattern, but I think eval is best solution here
data1 = eval(repr(data).replace('number', 'numbr'))
answered Oct 13, 2017 at 17:01
Kirill Ermolov
8107 silver badges20 bronze badges
1 Comment
thowi
Hey, thank you! Thats a smart, small solution :D But I'd indeed like to replace only the key, value can stay as is.
If you are trying to replace both keys and values this will work.
from json import dumps, loads
data = [{'address': {
'city': 'city A',
'company_name': 'company A'},
'amount': 998,
'items': [{'description': 'desc A1','number': 'number A1'}],
'number': 'number of A',
'service_date': {
'type': 'DEFAULT',
'date': '2015-11-18'},
'vat_option': 123},
{'address': {
'city': 'city B',
'company_name': 'company B'},
'amount': 222,
'items': [{'description': 'desc B1','number': 'number B1'},
{'description': 'desc B2','number': 'number B2'}],
'number': 'number of B',
'service_date': {
'type': 'DEFAULT',
'date': '2015-11-18'},
'vat_option': 456}
]
data_string = dumps(data)
data = loads(data_string.replace('number', 'numbr')
answered Oct 13, 2017 at 17:10
Dalvenjia
2,0731 gold badge15 silver badges17 bronze badges
1 Comment
thowi
Hey, thank you! Thats a smart, small solution :D But I'd indeed like to replace only the key, value can stay as is.
lang-py