列表中的词典列表

时间:2011-04-05 20:57:50

标签: python list dictionary

我希望在列表字典(所有相同长度)之间来回切换:

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

和词典列表:

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

我正在寻找在两种形式之间切换的最简洁方法。

13 个答案:

答案 0 :(得分:46)

对于那些喜欢聪明/ hacky单行的人。

以下为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)

LDDL有点粗暴,因为您假设每个dict中的密钥相同。此外,请注意,我不会宽恕在任何类型的真实系统中使用此类代码。

答案 1 :(得分:12)

要从词典列表中删除,这很简单:

您可以使用此表单:

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]}

或使用defaultdict

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]}]

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

答案 2 :(得分:10)

如果你被允许使用外包装,熊猫的效果非常好:

import pandas as pd
pd.DataFrame(DL).to_dict('list')

哪个输出:

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

答案 3 :(得分:8)

也许考虑使用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

答案 4 :(得分:5)

以下是我提出的单线解决方案(分布在多行以便于阅读):

如果dl是你原来的名单:

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

然后是如何将其转换为dicts列表:

ld = [{key:value[index] for key in dl.keys()}
         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)
         ))
      }

如果你使用的是Python 2而不是Python 3,那么你可以在那里使用reduce而不是functools.reduce

如果您假设列表中的所有词组都具有相同的键,则可以简化此操作:

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

答案 5 :(得分:4)

package fx; import javafx.animation.KeyFrame; import javafx.scene.control.TextField; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.animation.KeyValue; import javafx.animation.Timeline; import javafx.application.Application; import javafx.geometry.Bounds; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Slider; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; import javafx.scene.layout.VBox; import javafx.scene.shape.Circle; import javafx.stage.Stage; import javafx.util.Duration; import java.util.Random; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class GUI extends Application { public static void main (String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) throws Exception { Pane canvas = new Pane(); Scene scene = new Scene(canvas,1000, 500); Bounds bounds = canvas.getBoundsInLocal(); HBox hbox = new HBox(); hbox.setStyle("-fx-background-color: grey"); hbox.setPrefSize(1000, 40); hbox.setLayoutX(0); hbox.setLayoutY(460); TextField NrInput = new TextField(""); NrInput.setPromptText("Total amount of balls:"); NrInput.setPrefHeight(40); Button startBtn = new Button("Start"); startBtn.setPrefWidth(70); startBtn.setPrefHeight(40); startBtn.setOnAction(e ->{ startBtn.setDisable(true); //list with balls. lista med bollar ArrayList<Ball> balls = new ArrayList<>(); // Get text // Do a check. Gör typkontroll int ballCount = Integer.parseInt(NrInput.getText()); Random r = new Random(); int Low = 20; int High = 420; int id = 0; //System.out.println(bounds.getMaxX()); for (int i = 0; i < ballCount; i++) { Ball ball; // Randomize Y int y = r.nextInt(High-Low) + Low; //every other ball gets in different teams if (i % 2 == 0) { ball = new Ball(25, y, id, 0); } else { ball = new Ball(955, y, id, 1); } balls.add(ball); canvas.getChildren().add(ball.getCircle()); id = id + 1; } for (Ball b : balls) { b.moveBall(); } startBtn.setDisable(false); }); Button restartBtn = new Button("Restart"); restartBtn.setPrefWidth(70); restartBtn.setPrefHeight(40); restartBtn.setOnAction(e -> { }); Button exitBtn = new Button("Exit"); exitBtn.setPrefWidth(70); exitBtn.setPrefHeight(40); exitBtn.setOnAction(e -> primaryStage.close()); HBox spawnBlue = new HBox(); spawnBlue.setPrefHeight(420); spawnBlue.setPrefWidth(30); spawnBlue.setLayoutX(20); spawnBlue.setLayoutY(20); spawnBlue.setStyle("-fx-background-color: blue"); HBox spawnOrange = new HBox(); spawnOrange.setPrefHeight(420); spawnOrange.setPrefWidth(30); spawnOrange.setLayoutX(950); spawnOrange.setLayoutY(20); spawnOrange.setStyle("-fx-background-color: orange"); canvas.getChildren().add(hbox); canvas.getChildren().add(spawnOrange); canvas.getChildren().add(spawnBlue); hbox.getChildren().add(startBtn); hbox.getChildren().add(NrInput); hbox.getChildren().add(restartBtn); hbox.getChildren().add(exitBtn); primaryStage.setScene(scene); primaryStage.show(); } public void runTask() { } }`

Docs

cytoolz.dicttoolz.merge_with

非cython版本

Docs

from cytoolz.dicttoolz import merge_with

merge_with(list, *LD)

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

答案 6 :(得分:2)

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

In [1]: import pandas as pd

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

In [3]: pd.DataFrame(DL).to_dict('records')
Out[3]: [{'a': 0, 'b': 2}, {'a': 1, 'b': 3}]

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

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

答案 7 :(得分:1)

这是我的小脚本:

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)您认为列表的长度相同

答案 8 :(得分:1)

我能想到周末夏天最干净的方式。作为奖励,它支持不同长度的列表(但在这种情况下,DLtoLD(LDtoDL(l))不再具有身份)。

  1. 从列表到词典

    实际上不如@ dwerk的defaultdict版本干净。

    def LDtoDL (l) :
       result = {}
       for d in l :
          for k, v in d.items() :
             result[k] = result.get(k,[]) + [v] #inefficient
       return result
    
  2. 从dict到列表

    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
    

答案 9 :(得分:1)

这是不使用任何库的解决方案:

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}]

答案 10 :(得分:0)

如果您不介意生成器,可以使用类似

的内容
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异常。

另一方面,我无法弄清楚你实际想要做什么;设计一个满足您需求的数据结构而不是试图将其置于现有数据结构中可能更为明智。 (例如,dicts列表是表示数据库查询结果的不良方式。)

答案 11 :(得分:0)

我需要一种适用于不同长度列表的方法(所以这是对原始问题的概括)。由于我没有在这里找到任何符合我预期的代码,这里是我的代码:

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}]

答案 12 :(得分:-1)

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