词汇表与词汇表之间的词汇表

我想在(等长)列表的字典之间来回切换:

DL = {'a': [0, 1], 'b': [2, 3]}

以及一系列的字典:

LD = [{'a': 0, 'b': 2}, {'a': 1, 'b': 3}]
52621 次浏览

或许可以考虑使用 numpy:

import numpy as np


arr = np.array([(0, 2), (1, 3)], dtype=[('a', int), ('b', int)])
print(arr)
# [(0, 2) (1, 3)]

在这里,我们访问按名称索引的列,例如 'a''b'(有点像 DL) :

print(arr['a'])
# [0 1]

这里我们通过整数索引(有点像 LD)访问行:

print(arr[0])
# (0, 2)

行中的每个值都可以通过列名(类似于 LD)访问:

print(arr[0]['b'])
# 2

这是我的小剧本:

a = {'a': [0, 1], 'b': [2, 3]}
elem = {}
result = []


for i in a['a']: # (1)
for key, value in a.items():
elem[key] = value[i]
result.append(elem)
elem = {}


print result

我觉得这样不太好。

(1) 假设列表的长度相同

如果你不介意使用发电机,你可以使用

def f(dl):
l = list((k,v.__iter__()) for k,v in dl.items())
while True:
d = dict((k,i.next()) for k,i in l)
if not d:
break
yield d

由于技术上的原因,它没有那么“干净”: 我最初的实现是使用 yield dict(...)的,但是这最终变成了一个空字典,因为(在 Python 2.5中) a for b in c在遍历 c时没有区分 StopIteration 异常和在计算 a时区分 StopIteration 异常。

另一方面,我不知道您实际上想要做什么; 设计一个满足您需求的数据结构,而不是试图将其硬塞到现有的数据结构中,可能更为明智。(例如,用一列字典表示数据库查询的结果是一种糟糕的方法。)

To go from the list of dictionaries, it is straightforward:

你可使用以下表格:

DL={'a':[0,1],'b':[2,3], 'c':[4,5]}
LD=[{'a':0,'b':2, 'c':4},{'a':1,'b':3, 'c':5}]


nd={}
for d in LD:
for k,v in d.items():
try:
nd[k].append(v)
except KeyError:
nd[k]=[v]


print nd
#{'a': [0, 1], 'c': [4, 5], 'b': [2, 3]}

或使用 违约判决:

nd=cl.defaultdict(list)
for d in LD:
for key,val in d.items():
nd[key].append(val)


print dict(nd.items())
#{'a': [0, 1], 'c': [4, 5], 'b': [2, 3]}

走另一条路是有问题的。您需要从字典中的键中获得关于列表中插入顺序的一些信息。回想一下,dict 中键的顺序不一定与原始插入顺序相同。

对于傻笑,假设插入顺序是基于已排序的键。然后你可以这样做:

nl=[]
nl_index=[]


for k in sorted(DL.keys()):
nl.append({k:[]})
nl_index.append(k)


for key,l in DL.items():
for item in l:
nl[nl_index.index(key)][key].append(item)


print nl
#[{'a': [0, 1]}, {'b': [2, 3]}, {'c': [4, 5]}]

如果你的问题是基于好奇心,这就是你的答案。如果遇到实际问题,我建议您重新考虑一下数据结构。这些似乎都不是一个非常可扩展的解决方案。

这是我能想到的最干净的夏日星期五了。作为额外的好处,它支持不同长度的列表(但在本例中,DLtoLD(LDtoDL(l))不再是标识)。

  1. 从名单到结论

    实际上没有@dwerk 的默认版本干净。

    def LDtoDL (l) :
    result = {}
    for d in l :
    for k, v in d.items() :
    result[k] = result.get(k,[]) + [v] #inefficient
    return result
    
  2. From dict to list

    def DLtoLD (d) :
    if not d :
    return []
    #reserve as much *distinct* dicts as the longest sequence
    result = [{} for i in range(max (map (len, d.values())))]
    #fill each dict, one key at a time
    for k, seq in d.items() :
    for oneDict, oneValue in zip(result, seq) :
    oneDict[k] = oneValue
    return result
    

下面是我想出的一行解决方案(为了便于阅读,分散在多行中) :

如果 dl 是你列表的原始字典:

dl = {"a":[0, 1],"b":[2, 3]}

Then here's how to convert it to a list of dicts:

ld = [{key:value[index] for key,value in dl.items()}
for index in range(max(map(len,dl.values())))]

如果你假设你所有的列表都是相同的长度,你可以通过下面的方法简化并提高性能:

ld = [{key:value[index] for key, value in dl.items()}
for index in range(len(dl.values()[0]))]

以下是如何将其转换为列表的结语:

dl2 = {key:[item[key] for item in ld]
for key in list(functools.reduce(
lambda x, y: x.union(y),
(set(dicts.keys()) for dicts in ld)
))
}

如果您使用的是 Python2而不是 Python3,那么您可以在那里使用 reduce而不是 functools.reduce

如果你假设你列表中的所有字母都有相同的键,那么你可以简化它:

dl2 = {key:[item[key] for item in ld] for key in ld[0].keys() }

如果你被允许使用外部软件包,熊猫在这方面很有用:

import pandas as pd
pd.DataFrame(DL).to_dict(orient="records")

Which outputs:

[{'a': 0, 'b': 2}, {'a': 1, 'b': 3}]

还可以使用 orient="list"返回原始结构

{'a': [0, 1], 'b': [2, 3]}

那些喜欢俏皮话的人。

这里是 DLLD:

v = [dict(zip(DL,t)) for t in zip(*DL.values())]
print(v)

LDDL:

v = {k: [dic[k] for dic in LD] for k in LD[0]}
print(v)

LD to DL is a little hackier since you are assuming that the keys are the same in each dict. Also, please note that I do not condone the use of such code in any kind of real system.

pandas的 python 模块可以为您提供一个简单易懂的解决方案。作为@chiang 回答的补充,D-to-L 和 L-to-D 的解答如下:

import pandas as pd
DL = {'a': [0, 1], 'b': [2, 3]}
out1 = pd.DataFrame(DL).to_dict('records')

产出:

[{'a': 0, 'b': 2}, {'a': 1, 'b': 3}]

In the other direction:

LD = [{'a': 0, 'b': 2}, {'a': 1, 'b': 3}]
out2 = pd.DataFrame(LD).to_dict('list')

产出:

{'a': [0, 1], 'b': [2, 3]}

cytoolz.dicttoolz.merge_with

医生

from cytoolz.dicttoolz import merge_with


merge_with(list, *LD)


{'a': [0, 1], 'b': [2, 3]}

非 cython 版本

医生

from toolz.dicttoolz import merge_with


merge_with(list, *LD)


{'a': [0, 1], 'b': [2, 3]}

下面是一个不使用任何库的解决方案:

def dl_to_ld(initial):
finalList = []
neededLen = 0


for key in initial:
if(len(initial[key]) > neededLen):
neededLen = len(initial[key])


for i in range(neededLen):
finalList.append({})


for i in range(len(finalList)):
for key in initial:
try:
finalList[i][key] = initial[key][i]
except:
pass


return finalList

你可以这样称呼它:

dl = {'a':[0,1],'b':[2,3]}
print(dl_to_ld(dl))


#[{'a': 0, 'b': 2}, {'a': 1, 'b': 3}]
DL={'a':[0,1,2,3],'b':[2,3,4,5]}
LD=[{'a':0,'b':2},{'a':1,'b':3}]
Empty_list = []
Empty_dict = {}
# to find length of list in values of dictionry
len_list = 0
for i in DL.values():
if len_list < len(i):
len_list = len(i)


for k in range(len_list):
for i,j in DL.items():
Empty_dict[i] = j[k]
Empty_list.append(Empty_dict)
Empty_dict = {}
LD = Empty_list

我需要这样一个方法,它适用于 与众不同长度列表(因此这是原始问题的一个概括)。因为我没有在这里找到任何我期望的代码,这里是我的代码,为我工作:

def dict_of_lists_to_list_of_dicts(dict_of_lists: Dict[S, List[T]]) -> List[Dict[S, T]]:
keys = list(dict_of_lists.keys())
list_of_values = [dict_of_lists[key] for key in keys]
product = list(itertools.product(*list_of_values))


return [dict(zip(keys, product_elem)) for product_elem in product]

例子:

>>> dict_of_lists_to_list_of_dicts({1: [3], 2: [4, 5]})
[{1: 3, 2: 4}, {1: 3, 2: 5}]
>>> dict_of_lists_to_list_of_dicts({1: [3, 4], 2: [5]})
[{1: 3, 2: 5}, {1: 4, 2: 5}]
>>> dict_of_lists_to_list_of_dicts({1: [3, 4], 2: [5, 6]})
[{1: 3, 2: 5}, {1: 3, 2: 6}, {1: 4, 2: 5}, {1: 4, 2: 6}]
>>> dict_of_lists_to_list_of_dicts({1: [3, 4], 2: [5, 6], 7: [8, 9, 10]})
[{1: 3, 2: 5, 7: 8},
{1: 3, 2: 5, 7: 9},
{1: 3, 2: 5, 7: 10},
{1: 3, 2: 6, 7: 8},
{1: 3, 2: 6, 7: 9},
{1: 3, 2: 6, 7: 10},
{1: 4, 2: 5, 7: 8},
{1: 4, 2: 5, 7: 9},
{1: 4, 2: 5, 7: 10},
{1: 4, 2: 6, 7: 8},
{1: 4, 2: 6, 7: 9},
{1: 4, 2: 6, 7: 10}]

List of dicts ⟶ dict of lists

from collections import defaultdict
from typing import TypeVar


K = TypeVar("K")
V = TypeVar("V")




def ld_to_dl(ld: list[dict[K, V]]) -> dict[K, list[V]]:
dl = defaultdict(list)
for d in ld:
for k, v in d.items():
dl[k].append(v)
return dl

如果在键访问时不存在空列表,则 defaultdict 创建一个空列表。


清单清单

收集到“参差不齐”的字典

from typing import TypeVar


K = TypeVar("K")
V = TypeVar("V")




def dl_to_ld(dl: dict[K, list[V]]) -> list[dict[K, V]]:
ld = []
for k, vs in dl.items():
ld += [{} for _ in range(len(vs) - len(ld))]
for i, v in enumerate(vs):
ld[i][k] = v
return ld

这将生成一个字典 ld列表,如果 dl中的列表长度不等,这些字典可能会丢失项目。它循环遍历 dl中的所有键值,如果 ld没有足够的键值,则创建空字典。

只收集到“完整的”字典中

(通常仅用于等长列表。)

from typing import TypeVar


K = TypeVar("K")
V = TypeVar("V")




def dl_to_ld(dl: dict[K, list[V]]) -> list[dict[K, V]]:
ld = [dict(zip(dl.keys(), v)) for v in zip(*dl.values())]
return ld

这将生成具有 dl中最小列表长度的字典 ld列表。