【问题标题】:dict from a dict of list来自列表字典的字典
【发布时间】:2021-05-19 17:15:55
【问题描述】:

我有一个 Python 字典,格式如下:

d1 = {'Name':['ABC'], 'Number':['123'], 'Element 1':['1', '2', '3'],
      'Element2':['1','2','3']}

预期输出:

{'Name': 'ABC', 'Number': '123',
 'Elements': [{'Element 1': '1', 'Element2': '1'},
              {'Element 1': '2', 'Element2': '2'},
              {'Element 1': '3', 'Element2': '3'}]

我尝试了以下方法:

[{k: v[i] for k, v in d1.items() if i < len(v)}
    for i in range(max([len(l) for l in d1.values()]))]

但得到这个结果:

[{'Name': 'ABC', 'Number': '123', 'Element 1': '1', 'Element 2': '1'},
 {'Element 1': '2', 'Element 2': '2'},
 {'Element 1': '3', 'Element 2': '3'}]

我该怎么走?

【问题讨论】:

  • 如果您还包括尝试提供的内容时发生的情况,将对读者有所帮助
  • @avigil 添加了问题,谢谢

标签: python dictionary


【解决方案1】:

我强烈建议不要尝试在一行中完成所有操作。如果您有任何分支逻辑或嵌套循环,它并不总是更有效,而且几乎总是不太可读。

根据您的字典,我们可以将 pop() NameNumber 键输入到我们的新字典中。那么

output = dict()

d1 = {'Name':['ABC'], 'Number':['123'], 'Element 1':['1', '2', '3'], 'Element2':['1','2','3']}

output["Name"] = d1.pop("Name")
output["Number"] = d1.pop("Number")

print(output)
# prints:
# {'Name': ['ABC'], 'Number': ['123']}

print(d1)
# prints:
# {'Element 1': ['1', '2', '3'], 'Element2': ['1', '2', '3']}

然后,我们压缩字典中所有剩余的值,并将它们添加到一个新列表中:

mylist = []
keys = d1.keys()

for vals in zip(*d1.values()):
    temp_obj = dict(zip(keys, vals))
    mylist.append(temp_obj)

print(mylist)
# prints: 
# [{'Element 1': '1', 'Element2': '1'},
#  {'Element 1': '2', 'Element2': '2'},
#  {'Element 1': '3', 'Element2': '3'}]

最后,将其分配给output["Elements"]

output["Elements"] = mylist
print(output)
# prints:
# {'Name': ['ABC'], 'Number': ['123'], 'Elements': [{'Element 1': '1', 'Element2': '1'}, {'Element 1': '2', 'Element2': '2'}, {'Element 1': '3', 'Element2': '3'}]}

由于您不想硬编码前两个键,

for k, v in d1.items():
    if "element" not in k.lower():
        output[k] = v

或作为字典理解:

output = {k: v for k, v in d1.items() if "element" not in k.lower()}

【讨论】:

  • 非常感谢您的快速回答,是否可以不对“姓名”和“号码”键进行硬编码?
  • 是否可以假设对任何不包含 "Element" 的键应用相同的处理?查看最新编辑@Volume069
  • 现在“元素”是硬编码的...@Pranav Hosangadi
  • @Volume069 将if "element" not in k.lower() 更改为您想要的任何逻辑
  • 不确定,如何从这个地方继续,但还是谢谢。
【解决方案2】:

使用元组列表来创建字典的元素列表。使用 Convert 从元组构建您的字典项。

#https://www.geeksforgeeks.org/python-convert-list-tuples-dictionary/

d1 = {'Name':['ABC'], 'Number':['123'], 'Element 1':['1', '2', '3'],
  'Element2':['1','2','3']}

def Convert(tup, di):
    for a, b in tup:
       di[a]=b
    return di

dict={}
listElements=[]
for key,value in d1.items():
   if isinstance(value,list) and len(value)>1:
       for item in value:
           listElements.append((key,item))
   elif isinstance(value,list) and len(value)==1:
       dict[key]=value[0]
   else:
       dict[key]=value
    
 dict['Elements']=[Convert([(x,y)],{})  for x,y in listElements]
 print(dict)  

输出:

 {'Name': 'ABC', 'Number': '123', 'Elements': [{'Element 1': '1'}, {'Element 1': '2'}, {'Element 1': '3'}, {'Element2': '1'}, {'Element2': '2'}, {'Element2': '3'}]}  

【讨论】:

    【解决方案3】:

    我会一步一步解释:

    1. 我们构建new_d1 变量,这是您期望作为输出的字典,它被初始化为{'Name': 'ABC', 'Number': '123'}。为了实现上述目的,我们使用理解符号考虑到键 != 'Element'

      new_d1 = {key: d1.get(key)[0] for key in filter(lambda x: 'Element' not in x, d1)}
      
    2. 我们构建了elements 变量,这是一个包含对我们来说很重要的字典的列表,我的意思是,我们必须操作这些字典才能达到预期的结果。那么elements 就是[{'Element 1': ['1', '2', '3']}, {'Element2': ['1', '2', '3']}]

      elements = [{key: d1.get(key)} for key in filter(lambda x: 'Element' in x, d1)]
      
    3. 我们将使用itertools.product 进行笛卡尔积,同时考虑elements 中存在的每个键和每个值项

      product = [list(it.product(d.keys(), *d.values())) for d in elements]
      
    4. 使用zip,我们排列数据并将它们隐藏在字典中。最后我们在new_df1中创建"Elements"

      elements_list = [dict(t) for index, t in enumerate(list(zip(*product)))]
      new_d1["Elements"] = elements_list
      
      print(new_d1)
      

    完整代码:

    import itertools as it
    
    new_d1 = {key: d1.get(key)[0] for key in filter(lambda x: 'Element' not in x, d1)}
    elements = [{key: d1.get(key)} for key in filter(lambda x: 'Element' in x, d1)]
    product = [list(it.product(d.keys(), *d.values())) for d in elements]
    elements_list = [dict(t) for index, t in enumerate(list(zip(*product)))]
    new_d1["Elements"] = elements_list
    

    输出:

    {'Elements': [{'Element 1': '1', 'Element2': '1'},
                  {'Element 1': '2', 'Element2': '2'},
                  {'Element 1': '3', 'Element2': '3'}],
     'Name': 'ABC',
     'Number': '123'}
    

    【讨论】:

      猜你喜欢
      • 2011-07-30
      • 1970-01-01
      • 2018-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      相关资源
      最近更新 更多