简体   繁体   English

递归展平对象

[英]Recursively flatten an object

I have the following object: 我有以下对象:

d={
   'CollectionTitleIDs': {
           '852070#TVEpisode': '12', 
           '852063#TVEpisode': '4', 
           '852067#TVEpisode': '9'
     }, 
    'ReleaseYear': '2005', 
    'TVSeriesID': '5638#TVSeries'
}

I would like to flatten it to get the following output: 我想展平它以获得以下输出:

{
   'CollectionTitleIDs': [
      {"_Key": "852070#TVEpisode", "Value": "12"},
      {"_Key": "852063#TVEpisode", "Value": "4"},
      {"_Key": "852067#TVEpisode", "Value": "9"}
    ]
    'ReleaseYear': '2005', 
    'TVSeriesID': '5638#TVSeries'
}

In other words, if the value of the key is a dict, to push the keys of that dict to a "_Key" field and the value of that to a "Value" field. 换句话说,如果键的值是字典,则将该键的键推到“ _Key”字段,并将键的值推到“ Value”字段。

I've been having difficulty with the recursion. 我一直在递归有困难。 And currently I have something like this: 目前我有这样的事情:

What I currently have is: 我目前拥有的是:

def flatten_obj(obj, FLAT_OBJ=None):

    if FLAT_OBJ is None: FLAT_OBJ = OrderedDict()
    if isinstance(obj, list):
        return [flatten_obj(l, FLAT_OBJ=FLAT_OBJ) for l in obj]
    elif not isinstance(obj, dict):
        return obj
    else:
        for key in list(obj.keys()):
            val = get_sub_object_from_path(obj, key)
            if isinstance(val, dict):
                FLAT_OBJ[key] = [{'_Key': subkey, 'Value': flatten_obj(subval)} for subkey, subval in val.items()]
            elif isinstance(val, list):
                FLAT_OBJ[key] = flatten_obj(val, FLAT_OBJ=FLAT_OBJ)
            else:
                FLAT_OBJ[key] = val
    return FLAT_OBJ

Note that the above has one level of recursion, but it's possible the "value" will have a(nother) nested object as well, in which case we want to again extract the _Key,Value. 请注意,以上内容仅具有一个递归级别,但是“值”也可能具有(另一个)嵌套对象,在这种情况下,我们想再次提取_Key,Value。

You can use unpacking with a list comprehension: 您可以将解压缩与列表理解一起使用:

d = {'CollectionTitleIDs': {'852070#TVEpisode': '12', '852063#TVEpisode': '4', '852067#TVEpisode': '9'}, 'ReleaseYear': '2005', 'TVSeriesID': '5638#TVSeries'}
new_d = {**d, 'CollectionTitleIDs':[{'_Key':a, 'Value':b} for a, b in d['CollectionTitleIDs'].items()]}

Output: 输出:

{'CollectionTitleIDs': 
  [{'_Key': '852070#TVEpisode', 'Value': '12'}, 
   {'_Key': '852063#TVEpisode', 'Value': '4'}, 
   {'_Key': '852067#TVEpisode', 'Value': '9'}], 
 'ReleaseYear': '2005', 'TVSeriesID': '5638#TVSeries'}

The code should be simpler than that: 该代码应该比这更简单:

  1. If it's a list return the list of flattened objects 如果是列表,则返回展平对象的列表
  2. If it's a dict return a list of the key/val objects 如果是字典,则返回键/ val对象的列表
  3. otherwise just return x 否则就返回x

in code: 在代码中:

def flatten1(x):
    if isinstance(x, list):
        return [flatten1(y) for y in x]
    elif isinstance(x, dict):
        return [{"_Key": key, "Value": flatten1(value)}
                for key, value in x.items()]
    else:
        return x

In your example however for some reason the toplevel is not being flattened and is instead a regular dict, then just do so 但是,在您的示例中,由于某种原因, 顶层没有被扁平化,而是常规的dict,然后只需这样做

def flatten(x):
    if isinstance(x, dict):
       return {key: flatten1(value) for key, value in x.items()}
    else:
       return flatten1(x)

flatten1 could even be made an internal function: flatten1甚至可以做成内部函数:

def flatten(x):
    def flatten1(x):
        if isinstance(x, list):
            return [flatten1(y) for y in x]
        elif isinstance(x, dict):
            return [{"_Key": key, "Value": flatten1(value)}
                    for key, value in x.items()]
        else:
            return x

    if isinstance(x, dict):
       return {key: flatten1(value) for key, value in x.items()}
    else:
       return flatten1(x)

My Method: 我的方法:

d={
   'CollectionTitleIDs': {
           '852070#TVEpisode': '12', 
           '852063#TVEpisode': '4', 
           '852067#TVEpisode': '9'
     }, 
    'ReleaseYear': '2005', 
    'TVSeriesID': '5638#TVSeries'
}

d['CollectionTitleIDs'] = list(map(lambda x: {'_Key': x[0], 'Value': x[1]}, d['CollectionTitleIDs'].items()))

#{
#  'CollectionTitleIDs': [
#    {'_Key': '852070#TVEpisode', 'Value': '12'},
#    {'_Key': '852063#TVEpisode', 'Value': '4'}, 
#    {'_Key': '852067#TVEpisode', 'Value': '9'}
#  ], 
#  'ReleaseYear': '2005', 
#  'TVSeriesID': '5638#TVSeries'
#}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM