code

파이썬 목록을 사전으로 변환

codestyles 2020. 10. 28. 08:05
반응형

파이썬 목록을 사전으로 변환


이 질문에 이미 답변이 있습니다.

l = ["a", "b", "c", "d", "e"]

이 목록을 다음과 같은 사전으로 변환하고 싶습니다.

d = {"a": "b", "c": "d", "e": ""}

따라서 기본적으로 짝수는 키가되고 배당률은 값이됩니다. 나는 if 문이있는 for 루프와 같은 "비 파이썬 적"방식으로 그것을 할 수 있다는 것을 알고 있지만 이것을 달성하기 위해서는 더 "파이썬 적"방식이 있어야한다고 생각합니다. 그래서 어떤 도움을 주셔서 감사합니다 :)


일반적인 그룹화 레시피를 사용하여 다음을 수행 할 수 있습니다.

파이썬 2 :

d = dict(itertools.izip_longest(*[iter(l)] * 2, fillvalue=""))

파이썬 3 :

d = dict(itertools.zip_longest(*[iter(l)] * 2, fillvalue=""))

당신이 아직도 무엇을 생각하고 있다면! 당신은 혼자가 아닐 것입니다. 실제로 그렇게 복잡하지 않습니다. 설명하겠습니다.

내장 함수만을 사용하여 목록을 사전으로 바꾸는 방법

연속 짝수 항목에 매핑 된 키로 홀수 항목 (1부터 계산)을 사용하여 다음 목록을 사전으로 변환하려고합니다.

l = ["a", "b", "c", "d", "e"]

dict ()

사전을 생성하기 위해 우리는 매뉴얼에 따라 매핑 유형에dict 대한 내장 함수를 사용할 수 있으며 다음 방법이 지원됩니다.

dict(one=1, two=2)
dict({'one': 1, 'two': 2})
dict(zip(('one', 'two'), (1, 2)))
dict([['two', 2], ['one', 1]])

마지막 옵션은 2 개의 값 또는 (key, value)튜플이 있는 목록 목록을 제공하도록 제안 하므로 순차 목록을 다음과 같이 바꾸고 싶습니다.

l = [["a", "b"], ["c", "d"], ["e",]]

또한 설명서에서 설명하는 내장zip 기능 중 하나 인 기능에 대해서도 소개 합니다.

튜플 목록을 반환합니다. 여기서 i 번째 튜플은 각 인수의 i 번째 요소를 포함합니다.

즉 우리는 두 개의 목록으로 목록을 설정할 수 있습니다 경우 a, c, eb, d다음 zip나머지를 할 것입니다.

슬라이스 표기법

우리가 볼 수있는 슬라이싱문자열함께 사용되며 , 또한 주로 범위 또는 짧은 슬라이스 표기법을 사용 하는 목록 섹션 에서 더 진행 되지만 이것이 긴 슬라이스 표기법의 모양과 단계로 수행 할 수있는 것입니다 .

>>> l[::2]
['a', 'c', 'e']

>>> l[1::2]
['b', 'd']

>>> zip(['a', 'c', 'e'], ['b', 'd'])
[('a', 'b'), ('c', 'd')]

>>> dict(zip(l[::2], l[1::2]))
{'a': 'b', 'c': 'd'}

이것이 관련된 메커니즘을 이해하는 가장 간단한 방법 임에도 불구하고이 복제 예제에서 볼 수 있듯이 슬라이스는 매번 새로운 목록 객체이기 때문에 단점이 있습니다.

>>> a = [1, 2, 3]
>>> b = a
>>> b
[1, 2, 3]

>>> b is a
True

>>> b = a[:]
>>> b
[1, 2, 3]

>>> b is a
False

b가 a처럼 보이지만 이제는 두 개의 개별 객체이므로 대신 그루퍼 레시피 를 사용하는 것을 선호합니다 .

그루퍼 레시피

그룹화는 itertools 모듈의 일부로 설명되지만 기본 기능에서도 완벽하게 작동합니다.

심각한 부두교 맞죠? =) 그러나 실제로 향신료에 대한 약간의 구문 설탕에 지나지 않습니다. 그루퍼 레시피는 다음 식으로 수행됩니다.

*[iter(l)]*2

어느 정도 의미가있는 경우 목록에 래핑 된 동일한 반복자의 두 인수로 변환됩니다. 빛을 비추는 데 도움이되도록 분해 해 보겠습니다.

zip for shortest

>>> l*2
['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e']

>>> [l]*2
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]

>>> [iter(l)]*2
[<listiterator object at 0x100486450>, <listiterator object at 0x100486450>]

>>> zip([iter(l)]*2)
[(<listiterator object at 0x1004865d0>,),(<listiterator object at 0x1004865d0>,)]

>>> zip(*[iter(l)]*2)
[('a', 'b'), ('c', 'd')]

>>> dict(zip(*[iter(l)]*2))
{'a': 'b', 'c': 'd'}

보시다시피 두 반복자의 주소가 동일하게 유지되므로 zip이 먼저 키를 가져온 다음 값과 키와 값을 가져 오는 동일한 반복기를 사용하여 작업을 수행하고 있습니다. 슬라이스로 훨씬 더 생산적으로.

당신은 더 작은 무엇 을 운반하는 다음과 같이 매우 동일하게 성취 할 것입니다 . 아마도 요인.

>>> it = iter(l)     
>>> dict(zip(it, it))
{'a': 'b', 'c': 'd'}

What about the empty key e if you've noticed it has been missing from all the examples which is because zip picks the shortest of the two arguments, so what are we to do.

Well one solution might be adding an empty value to odd length lists, you may choose to use append and an if statement which would do the trick, albeit slightly boring, right?

>>> if len(l) % 2:
...     l.append("")

>>> l
['a', 'b', 'c', 'd', 'e', '']

>>> dict(zip(*[iter(l)]*2))
{'a': 'b', 'c': 'd', 'e': ''}

Now before you shrug away to go type from itertools import izip_longest you may be surprised to know it is not required, we can accomplish the same, even better IMHO, with the built in functions alone.

map for longest

I prefer to use the map() function instead of izip_longest() which not only uses shorter syntax doesn't require an import but it can assign an actual None empty value when required, automagically.

>>> l = ["a", "b", "c", "d", "e"]
>>> l
['a', 'b', 'c', 'd', 'e']

>>> dict(map(None, *[iter(l)]*2))
{'a': 'b', 'c': 'd', 'e': None} 

Comparing performance of the two methods, as pointed out by KursedMetal, it is clear that the itertools module far outperforms the map function on large volumes, as a benchmark against 10 million records show.

$ time python -c 'dict(map(None, *[iter(range(10000000))]*2))'
real    0m3.755s
user    0m2.815s
sys     0m0.869s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(10000000))]*2, fillvalue=None))'
real    0m2.102s
user    0m1.451s
sys     0m0.539s

However the cost of importing the module has its toll on smaller datasets with map returning much quicker up to around 100 thousand records when they start arriving head to head.

$ time python -c 'dict(map(None, *[iter(range(100))]*2))'
real    0m0.046s
user    0m0.029s
sys     0m0.015s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100))]*2, fillvalue=None))'
real    0m0.067s
user    0m0.042s
sys     0m0.021s

$ time python -c 'dict(map(None, *[iter(range(100000))]*2))'
real    0m0.074s
user    0m0.050s
sys     0m0.022s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100000))]*2, fillvalue=None))'
real    0m0.075s
user    0m0.047s
sys     0m0.024s

See nothing to it! =)

nJoy!


I'd go for recursions:

l = ['a', 'b', 'c', 'd', 'e', ' ']
d = dict([(k, v) for k,v in zip (l[::2], l[1::2])])

Not sure whether it would help you or not but it works to me:

l = ["a", "b", "c", "d", "e"]
outRes = dict((l[i], l[i+1]) if i+1 < len(l) else (l[i], '') for i in xrange(len(l)))

참고URL : https://stackoverflow.com/questions/6900955/python-convert-list-to-dictionary

반응형