0

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
6
  • 1
    it should rename only keys? Post the expected result Commented 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'}}] Commented Oct 13, 2017 at 17:55
  • I've asked for the expected result, not the actual Commented 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'}}] Commented Oct 13, 2017 at 18:00
  • So each key number -> numbr. Values stay as they are. Commented Oct 13, 2017 at 18:00

3 Answers 3

1

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

3 Comments

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',
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...
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
0

eval function is anti pattern, but I think eval is best solution here

data1 = eval(repr(data).replace('number', 'numbr'))

1 Comment

Hey, thank you! Thats a smart, small solution :D But I'd indeed like to replace only the key, value can stay as is.
0

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')

1 Comment

Hey, thank you! Thats a smart, small solution :D But I'd indeed like to replace only the key, value can stay as is.

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.