如何在任意结构化数据中替换关键字的所有实例?

时间:2017-07-22 11:24:29

标签: python dictionary

我想替换可能具有复杂结构的字典中的kw(例如,值可能是字母或列表。这些字母也应该替换它们的kw,列表元素可能是哪个也应该被替换。)我写了以下

def replace_kw(obj,replace_this,with_this):
    print('object is '+str(obj))
    if isinstance(obj,dict):
        for k,v in obj.iteritems():
            if k==replace_this:
                obj[with_this]=obj[replace_this]
                del(obj[replace_this])
            else:
                obj[k] = replace_kw(obj[k],replace_this,with_this)
    elif isinstance(obj,list):
        for l in obj:
            l = replace_kw(l,replace_this,with_this)    
    return obj

它适用于我已经讨论过的简单示例,但我很好奇其他方法以及可能出错的地方。例如,我检查了一个关键字是否可以是字典,似乎答案是否定的,这样我就不会出错。

我给出的例子是

  d = {'data': [{'bbox_xywh': [838, 533, 50, 68], 'object': 'truck'},
{'bbox_xywh': [930, 563, 60, 57], 'object': 'car'}, 
{'bbox_xywh': [993, 560, 78, 56], 'object': 'car'}, 
{'bbox_xywh': [997, 565, 57, 39], 'object': 'car'}, 
{'bbox_xywh': [1094, 542, 194, 126], 'object': 'car'}, 
{'bbox_xywh': [1311, 539, 36, 74], 'object': 'person'}], 
'dimensions_h_w_c': (1200, 1920, 3), 
'filename':'/data/jeremy/image_dbs/hls/voc_rio_udacity_kitti_insecam_shuf_no_aug_test/1478020901220540088.jpg'}

replace_kw(d,'bbox_xywh','bbox')

{'data': [{'bbox': [838, 533, 50, 68], 'object': 'truck'},
  {'bbox': [930, 563, 60, 57], 'object': 'car'},
  {'bbox': [993, 560, 78, 56], 'object': 'car'},
  {'bbox': [997, 565, 57, 39], 'object': 'car'},
  {'bbox': [1094, 542, 194, 126], 'object': 'car'},
  {'bbox': [1311, 539, 36, 74], 'object': 'person'}],
 'dimensions_h_w_c': (1200, 1920, 3),
 'filename': '/data/jeremy/image_dbs/hls/voc_rio_udacity_kitti_insecam_shuf_no_aug_test/1478020901220540088.jpg'}

按预期工作

2 个答案:

答案 0 :(得分:1)

json

快速简单的解决方案包括使用json将整个事物转换为包含re.sub的字符串,然后将其转换回来:

import json, re
json.loads(re.sub('(?<=")bbox_xywh(?=":)', 'bbox', json.dumps(d), flags=re.M))

{'data': [{'bbox': [838, 533, 50, 68], 'object': 'truck'},
  {'bbox': [930, 563, 60, 57], 'object': 'car'},
  {'bbox': [993, 560, 78, 56], 'object': 'car'},
  {'bbox': [997, 565, 57, 39], 'object': 'car'},
  {'bbox': [1094, 542, 194, 126], 'object': 'car'},
  {'bbox': [1311, 539, 36, 74], 'object': 'person'}],
 'dimensions_h_w_c': [1200, 1920, 3],
 'filename': '/data/jeremy/image_dbs/hls/voc_rio_udacity_kitti_insecam_shuf_no_aug_test/1478020901220540088.jpg'}

您也可以考虑使用str.replace代替正则表达式(稍快):

json.loads(json.dumps(d).replace('"bbox_xywh":', '"bbox":'))

相信json它会一致地对您的数据进行字符串化。您可以像这样处理任意结构的字典。

当您的数据不符合JSON时,此操作失败 - 如果除了列表和dicts或自定义类对象之外还有其他python对象,则此操作不再有效。

literal_eval

以下是使用ast.literal_eval克服上述问题的另一种方法:

import ast
ast.literal_eval(str(d).replace('\'bbox_xywh\':', '\'bbox\':'))

虽然它没有强制列表中的元组,但我不喜欢这个,因为引号必须非常小心。

答案 1 :(得分:0)

def rep_str(obj, replace_this, with_this):
    if isinstance(obj, str):
        return obj.replace(replace_this, with_this)
    return obj

def change(obj, replace_this, with_this):
    if isinstance(obj, list):
        return [change(x, replace_this, with_this) for x in obj]
    if isinstance(obj, dict):
        return {rep_str(k, replace_this, with_this): 
            change(v, replace_this, with_this) for k, v in obj.items()}
    return obj

更改(obj,replace_this,with_this)