program story

딕셔너리 목록과의 딕셔너리 목록

inputbox 2021. 1. 7. 07:56
반응형

딕셔너리 목록과의 딕셔너리 목록


목록 사전 (모두 길이가 같음)간에 앞뒤로 변경하려고합니다.

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

및 사전 목록 :

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

두 가지 양식을 전환하는 가장 깨끗한 방법을 찾고 있습니다.


아마도 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

영리한 / 해키 한 줄을 즐기는 사람들을 위해.

여기 DL에 있습니다 LD:

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)

LDto DL는 키가 각각 동일하다고 가정하기 때문에 약간 해커 dict입니다. 또한 실제 시스템에서 이러한 코드를 사용하는 것을 용납하지 않습니다.


사전 목록에서 이동하는 것은 간단합니다.

이 양식을 사용할 수 있습니다.

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

다른 길로가는 것은 문제가됩니다. 사전의 키에서 목록에 삽입 순서 정보가 있어야합니다. 딕셔너리의 키 순서가 원래 삽입 순서와 반드시 동일하지는 않습니다.

웃음의 경우 삽입 순서가 정렬 된 키를 기반으로한다고 가정합니다. 그런 다음 다음과 같이 할 수 있습니다.

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

호기심에 근거한 질문이라면 답이 있습니다. 실제 문제가있는 경우 데이터 구조를 재고 해 보도록 제안하겠습니다. 이들 중 어느 것도 확장 가능한 솔루션이 아닌 것 같습니다.


외부 패키지를 사용할 수 있다면 Pandas는 다음과 같이 잘 작동합니다.

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

출력되는 내용 :

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

다음은 내가 생각 해낸 한 줄 솔루션 (가독성을 위해 여러 줄에 걸쳐 있음)입니다.

dl이 목록의 원래 사전 인 경우 :

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

그런 다음이를 사전 목록으로 변환하는 방법은 다음과 같습니다.

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 3 대신 Python 2를 사용 reduce하는 경우 대신 사용할 수 있습니다 functools.reduce.

목록의 모든 사전에 동일한 키가 있다고 가정하면이를 단순화 할 수 있습니다.

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

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

의 python 모듈은 pandas이해하기 쉬운 솔루션을 제공 할 수 있습니다. @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]}

여기 내 작은 스크립트 :

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) 목록 길이가 같다고 가정합니다.


내가 여름 금요일을 생각할 수있는 가장 깨끗한 방법. 보너스로 길이가 다른 목록을 지원합니다 (이 경우 DLtoLD(LDtoDL(l))더 이상 신원이 아닙니다).

  1. 목록에서 dict로

    @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
    

다음은 라이브러리를 사용하지 않는 솔루션입니다.

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

발전기가 마음에 들지 않으면 다음과 같은 것을 사용할 수 있습니다.

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

It's not as "clean" as it could be for Technical Reasons: My original implementation did yield dict(...), but this ends up being the empty dictionary because (in Python 2.5) a for b in c does not distinguish between a StopIteration exception when iterating over c and a StopIteration exception when evaluating a.

On the other hand, I can't work out what you're actually trying to do; it might be more sensible to design a data structure that meets your requirements instead of trying to shoehorn it in to the existing data structures. (For example, a list of dicts is a poor way to represent the result of a database query.)


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

ReferenceURL : https://stackoverflow.com/questions/5558418/list-of-dicts-to-from-dict-of-lists

반응형