通过将列表索引视为python中的键将dict中的所有列表转换为dict

时间:2019-03-21 06:04:34

标签: python python-3.x python-2.7 list dictionary

我正在尝试通过将列表索引作为键将dict中的所有列表转换为dict。

样本输入

{
    "checksum": "c540fcd985bf88c87e48c2bfa1df5498",
    "data": {
        "sampleMetrics": {
            "name": "DNA Library QC Metrics",
            "passQualityControl": true,
            "metrics": [{
                "name": "CONTAMINATION_SCORE",
                "value": 1302,
                "LSL": 0,
                "USL": 3106,
                "UOM": "NA"
            }]
        }
    }
}

预期输出

{
    "checksum": "c540fcd985bf88c87e48c2bfa1df5498",
    "data": {
        "sampleMetrics": {
            "name": "DNA Library QC Metrics",
            "passQualityControl": true,
            "metrics": {
                "0": {
                    "name": "CONTAMINATION_SCORE"
                },
                "1": {
                    "value": 1302
                },
                "2": {
                    "LSL": 0
                },
                "3": {
                    "USL": 3106
                },
                "4": {
                    "UOM": "NA"
                }
            }
        }
    }
}

试用

def list_to_dict_by_index(lst):
    print  {str(k): str(v) for k, v in enumerate(lst)}

list_to_dict_by_index([ {"d1" : 1}, {"d2" : 2} ])

但这适用于简单的列表。 如何对字典中的所有列表执行相同的操作?

(无论字典在哪里,都在列表中。)

列表可能包含另一个列表

例如: 样本输入2

"metrics": [{
    "name": ["CONTAMINATION_SCORE", "TOTAL_SCORE"],
    "value": 1302,
    "LSL": 0,
    "USL": 3106,
    "UOM": "NA"
}]

示例输出2

"metrics" : {
    "0": {
        "name": {
            "0": "CONTAMINATION_SCORE",
            "1": "TOTAL_SCORE"
        }
    },
    "1": {
        "value": 1302
    },
    "2": {
        "LSL": 0
    },
    "3": {
        "USL": 3106
    },
    "4": {
        "UOM": "NA"
    }
}

3 个答案:

答案 0 :(得分:0)

dic = {
    "checksum": "c540fcd985bf88c87e48c2bfa1df5498",
    "data": {
        "sampleMetrics": {
            "name": "DNA Library QC Metrics",
            "passQualityControl": True,
            "metrics": [{
                "name": "CONTAMINATION_SCORE",
                "value": 1302,
                "LSL": 0,
                "USL": 3106,
                "UOM": "NA"
            }]
        }
    }
}

dic2 = dic['data']['sampleMetrics']['metrics']
dic3 ={}
for i in dic2:
    for index,  j in enumerate(i,0):
        dic3[index]={j:i[j]}

dic['data']['sampleMetrics']['metrics'] = dic3

print(dic)

"""
output 
{
  'checksum': 'c540fcd985bf88c87e48c2bfa1df5498', 
  'data': {
           'sampleMetrics': {
                  'name': 'DNA Library QC Metrics',
                  'passQualityControl': True,
                  'metrics': {
                        0: {
                              'name': 'CONTAMINATION_SCORE'
                            },
                        1: {
                            'value': 1302
                            }, 
                        2: { 
                                'LSL': 0
                           },
                        3: {
                            'USL': 3106
                           },
                        4: {
                              'UOM': 'NA'
                            }
                            }
                           }
        }
}
"""

答案 1 :(得分:0)

您的第二个示例输入/输出包含与问题标题一致的组件,即,将列表转换为以列表索引为键的字典:

# input
"name": ["CONTAMINATION_SCORE", "TOTAL_SCORE"]

# output
"name": {
    "0": "CONTAMINATION_SCORE",
    "1": "TOTAL_SCORE"
}

但是,两个示例输入/输出均包含字典列表,这些列表预期将以不同的方式转换,即转换为字典字典,并且将键作为字典条目的可枚举索引。

# input
"metrics": [{
    ...
    "USL": 3106,
    "UOM": "NA"
}]

# output
"metrics" : {
    ...
    "3": {
        "USL": 3106
    },
    "4": {
        "UOM": "NA"
    }
}

很多单词试图从本质上阐明以下两种情况:

  1. {[{'foo': 'bar'}]} => {'0': {'foo': 'bar'}}
  2. {'foo': ['bar']} => {'foo': {'0': 'bar'}}

这可能是您失败的根源。此外,您尝试解决方案仅在字典的最顶层进行迭代。如果要影响任意级别的条目,则必须递归遍历字典,即,您需要某种形式:

from collections import abv
def update(d):
    for k, v in d.copy().items():
        if isinstance(v, abc.Mapping):
            d[k] = update(v)
        else:
            d[k] = iv
    return d

如果您使用的是python 2而不是python 3,请使用iteritems而不是item。此外,必须进行复制,以便在对字典进行突变时不会使迭代器无效。

您可以像最初用来获取有效解决方案那样,在枚举循环中工作。小心添加递归调用以影响字典的所有级别。总的来说,这可能类似于以下内容:

from collections import abc

def list_of_dict_to_dict(d):
    dd = {}
    for i, (key, val) in enumerate(d.copy().items()):
        dd[i] = {}
        if isinstance(val, abc.Mapping):
            dd[i][key] = transform_dict(val)
        elif isinstance(val, list):
            dd[i][key] = list_to_dict(val)
        else:
            dd[i][key] = val
    return dd

def list_to_dict(l):
    d = {}
    for i, val in enumerate(l):
        if isinstance(val, abc.Mapping):
            d[i] = transform_dict(val)
        else:
            d[i] = val
    return d

def transform_dict(d):
    for k, v in d.copy().items():
        if isinstance(v, list):
            if isinstance(v[0], abc.Mapping) and len(v) == 1:
                d[k] = list_of_dict_to_dict(v[0])
            else:
                d[k] = list_to_dict(v)
        elif isinstance(v, abc.Mapping):
            d[k] = transform_dict(v)
        else:
            d[k] = v
    return d

这假定字典列表的情况始终包含单个字典。在其他情况下,您的期望还不清楚。

答案 2 :(得分:0)

您的要求很明确,但是您的第一个示例与“将列表索引作为键将dict中的所有列表转换为dict”的规则不匹配。 metrics键映射到具有一个元素的列表,该元素是字典:[{...}]。因此,您的预期输出是:

...
        "metrics": {
            "0": {
                "name": "CONTAMINATION_SCORE",
                "value": 1302,
                "LSL": 0,
                "USL": 3106,
                "UOM": "NA"
            }
        }
...

如果这是您想要的,则只需使用DFS

def list_to_dict_by_key(json_value):
    if isinstance(json_value, list):
        return {str(i):list_to_dict_by_key(v) for i,v in enumerate(json_value)}
    elif isinstance(json_value, dict):
        return {k:list_to_dict_by_key(v) for k,v in json_value.items()}
    else:
        return json_value

列表被字典替换。字典的值被处理。

>>> list_to_dict_by_key(sample1)
{'checksum': 'c540fcd985bf88c87e48c2bfa1df5498', 'data': {'sampleMetrics': {'name': 'DNA Library QC Metrics', 'passQualityControl': True, 'metrics': {'0': {'name': 'CONTAMINATION_SCORE', 'value': 1302, 'LSL': 0, 'USL': 3106, 'UOM': 'NA'}}}}}
>>> list_to_dict_by_key(sample2)
{'checksum': 'c540fcd985bf88c87e48c2bfa1df5498', 'data': {'sampleMetrics': {'name': 'DNA Library QC Metrics', 'passQualityControl': True, 'metrics': {'0': {'name': {'0': 'CONTAMINATION_SCORE', '1': 'TOTAL_SCORE'}, 'value': 1302, 'LSL': 0, 'USL': 3106, 'UOM': 'NA'}}}}}

编辑sample1是您的第一个样本输入,而sample2几乎是相同的:"name": ["CONTAMINATION_SCORE", "TOTAL_SCORE"]替换了{{ 1}}