programing

사전에서 키-값 쌍의 하위 집합을 추출하시겠습니까?

iphone6s 2023. 4. 12. 21:55
반응형

사전에서 키-값 쌍의 하위 집합을 추출하시겠습니까?

여러 개의 키 값 쌍(16개 정도)이 있는 큰 사전 개체가 있지만, 관심 있는 것은 그 중 3개뿐입니다.이러한 사전을 서브셋하는 가장 좋은 방법(가장 짧은 방법/효율적 방법/가장 우아한 방법)은 무엇입니까?

내가 아는 건

bigdict = {'a':1,'b':2,....,'z':26} 
subdict = {'l':bigdict['l'], 'm':bigdict['m'], 'n':bigdict['n']}

나는 이것보다 더 우아한 방법이 있다고 확신한다.

다음을 시도해 보십시오.

dict((k, bigdict[k]) for k in ('l', 'm', 'n'))

또는 Python 3 Python 버전 2.7 이후(Favio Diniz가 2.7에서도 작동한다고 지적해 준 덕분에):

{k: bigdict[k] for k in ('l', 'm', 'n')}

업데이트: Havard S가 지적한 바와 같이, 사전에서 키가 나올 것을 알고 있을 것입니다.만약 당신이 그 가정을 할 수 없다면 그의 답변을 참조하십시오.또는 timbo가 코멘트에서 지적한 바와 같이, 에서 누락된 키를 원할 경우bigdictNone , , 하다, 하다, 하다, 하다.

{k: bigdict.get(k, None) for k in ('l', 'm', 'n')}

Python 3을 사용하고 있으며, 새로운 dict에 실제로 존재하는 키만 원하는 경우, 이 사실을 사용하여 개체를 보고 몇 가지 설정 작업을 수행할 수 있습니다.

{k: bigdict[k] for k in bigdict.keys() & {'l', 'm', 'n'}}

조금 더 짧게, 적어도:

wanted_keys = ['l', 'm', 'n'] # The keys you want
dict((k, bigdict[k]) for k in wanted_keys if k in bigdict)

전술한 모든 방법에 대한 속도 비교:

2020.07.13 업데이트(thx to @user3780389) : bigdict 키만 해당.

 IPython 5.5.0 -- An enhanced Interactive Python.
Python 2.7.18 (default, Aug  8 2019, 00:00:00) 
[GCC 7.3.1 20180303 (Red Hat 7.3.1-5)] on linux2
import numpy.random as nprnd
  ...: keys = nprnd.randint(100000, size=10000)
  ...: bigdict = dict([(_, nprnd.rand()) for _ in range(100000)])
  ...: 
  ...: %timeit {key:bigdict[key] for key in keys}
  ...: %timeit dict((key, bigdict[key]) for key in keys)
  ...: %timeit dict(map(lambda k: (k, bigdict[k]), keys))
  ...: %timeit {key:bigdict[key] for key in set(keys) & set(bigdict.keys())}
  ...: %timeit dict(filter(lambda i:i[0] in keys, bigdict.items()))
  ...: %timeit {key:value for key, value in bigdict.items() if key in keys}
100 loops, best of 3: 2.36 ms per loop
100 loops, best of 3: 2.87 ms per loop
100 loops, best of 3: 3.65 ms per loop
100 loops, best of 3: 7.14 ms per loop
1 loop, best of 3: 577 ms per loop
1 loop, best of 3: 563 ms per loop

예상대로라면 사전 이해가 가장 좋은 옵션입니다.

interesting_keys = ('l', 'm', 'n')
subdict = {x: bigdict[x] for x in interesting_keys if x in bigdict}

이 답변은 선택한 답변과 유사한 사전 이해를 사용하지만 누락된 항목을 제외하고는 사용되지 않습니다.

python 2 버전:

{k:v for k, v in bigDict.iteritems() if k in ('l', 'm', 'n')}

python 3 버전:

{k:v for k, v in bigDict.items() if k in ('l', 'm', 'n')}

대부분의 키를 유지하면서 몇 개의 키를 삭제하는 경우 대체 접근법:

{k: bigdict[k] for k in bigdict.keys() if k not in ['l', 'm', 'n']}

아마도:

subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n']])

Python 3은 다음을 지원합니다.

subdict={a:bigdict[a] for a in ['l','m','n']}

다음과 같이 사전에 존재 여부를 확인할 수 있습니다.

subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n'] if x in bigdict])

python 3에 대한 respon.

subdict={a:bigdict[a] for a in ['l','m','n'] if a in bigdict}

이 경우에도 하실 수 있습니다.map(어쨌든 이것은 알기 위한 매우 유용한 함수입니다).

sd = dict(map(lambda k: (k, l.get(k, None)), l))

예:

large_dictionary = {'a1':123, 'a2':45, 'a3':344}
list_of_keys = ['a1', 'a3']
small_dictionary = dict(map(lambda key: (key, large_dictionary.get(key, None)), list_of_keys))

: ..get(key, None) from from from :)

네, 몇 번인가 신경이 쓰이는 일이었습니다만, 부탁해 주신 Jayesh씨께 감사드립니다.

위의 답변은 다른 솔루션과 마찬가지로 좋은 솔루션처럼 보이지만, 코드 전체에 이 솔루션을 사용하고 있다면 IMHO 기능을 랩하는 것이 좋습니다.또한 여기에는 두 가지 사용 사례가 있습니다. 하나는 모든 키워드가 원본 사전에 있는지 여부를 고려하는 경우와 그렇지 않은 경우입니다.둘 다 동등하게 취급하면 좋을 것 같아요.

그래서 2펜스짜리 가치로 사전의 하위 클래스를 작성하는 것을 추천합니다.

class my_dict(dict):
    def subdict(self, keywords, fragile=False):
        d = {}
        for k in keywords:
            try:
                d[k] = self[k]
            except KeyError:
                if fragile:
                    raise
        return d

이제 다음 서브사전을 꺼낼 수 있습니다.

orig_dict.subdict(keywords)

사용 예:

#
## our keywords are letters of the alphabet
keywords = 'abcdefghijklmnopqrstuvwxyz'
#
## our dictionary maps letters to their index
d = my_dict([(k,i) for i,k in enumerate(keywords)])
print('Original dictionary:\n%r\n\n' % (d,))
#
## constructing a sub-dictionary with good keywords
oddkeywords = keywords[::2]
subd = d.subdict(oddkeywords)
print('Dictionary from odd numbered keys:\n%r\n\n' % (subd,))
#
## constructing a sub-dictionary with mixture of good and bad keywords
somebadkeywords = keywords[1::2] + 'A'
try:
    subd2 = d.subdict(somebadkeywords)
    print("We shouldn't see this message")
except KeyError:
    print("subd2 construction fails:")
    print("\toriginal dictionary doesn't contain some keys\n\n")
#
## Trying again with fragile set to false
try:
    subd3 = d.subdict(somebadkeywords, fragile=False)
    print('Dictionary constructed using some bad keys:\n%r\n\n' % (subd3,))
except KeyError:
    print("We shouldn't see this message")

위의 코드를 모두 실행하면 다음과 같은 출력이 표시됩니다(포맷에 대해서는 죄송합니다).

원본 사전:
{'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': 6, 'f': 5, 'i': 8, 'h': 7, 'k': 10, 'j': 9, 'm': 12, 'l': 11, 'o' 14, 'n'p': 16, 16

홀수 키의 사전:
{'a': 0, 'c': 2, 'e': 4, 'g': 6, 'i': 8, 'k': 10, 'm': 12, 'o': 14, 'q': 16, 's': 18, 'u': 20, 'w': 22, 'y': 24}

subd2 구축 실패:
원본 사전에는 일부 키가 포함되어 있지 않습니다.

잘못된 키를 사용하여 구성된 사전:
{'b': 1, 'd': 3, 'f': 5, 'h': 7, 'j': 9, 'l': 11, 'n': 13, 'p': 15, 'r': 17, 't': 19, 'v': 21, 'x': 23, 'z': 25}

또 하나 (마크 롱에어의 답변이 더 좋습니다)

di = {'a':1,'b':2,'c':3}
req = ['a','c','w']
dict([i for i in di.iteritems() if i[0] in di and i[0] in req])

해결 방법

from operator import itemgetter
from typing import List, Dict, Union


def subdict(d: Union[Dict, List], columns: List[str]) -> Union[Dict, List[Dict]]:
    """Return a dict or list of dicts with subset of 
    columns from the d argument.
    """
    getter = itemgetter(*columns)

    if isinstance(d, list):
        result = []
        for subset in map(getter, d):
            record = dict(zip(columns, subset))
            result.append(record)
        return result
    elif isinstance(d, dict):
        return dict(zip(columns, getter(d)))

    raise ValueError('Unsupported type for `d`')

사용 예

# pure dict

d = dict(a=1, b=2, c=3)
print(subdict(d, ['a', 'c']))

>>> In [5]: {'a': 1, 'c': 3}
# list of dicts

d = [
    dict(a=1, b=2, c=3),
    dict(a=2, b=4, c=6),
    dict(a=4, b=8, c=12),
]

print(subdict(d, ['a', 'c']))

>>> In [5]: [{'a': 1, 'c': 3}, {'a': 2, 'c': 6}, {'a': 4, 'c': 12}]

py3.8+의 다른 방법으로None누락된 키의 값big_dict는 바다코끼리를 사용합니다.

small_dict = {key: val for key in ('l', 'm', 'n') if (val := big_dict.get(key))}

지도(반쪽 단럼프 답안)를 사용하는 것이 가장 좋지만, 시간을 재지는 않았습니다만...

그러나 사전을 찾고 big_dict가 있는 경우:

  1. 반드시 요구 사항을 통과해야 합니다.이는 매우 중요하며 알고리즘 실행 시간에 영향을 미칩니다(큰 O, Theta, 이름 지정).
  2. 키가 없는 경우 오류를 방지할 수 있도록 범용적으로 작성하십시오.

예:

big_dict = {'a':1,'b':2,'c':3,................................................}
req = ['a','c','w']

{k:big_dict.get(k,None) for k in req )
# or 
{k:big_dict[k] for k in req if k in big_dict)

반대로 요구는 크지만 my_dict는 작다는 점에 유의하십시오.대신 my_dict를 루프해야 합니다.

일반적으로 교집합을 하고 있으며 문제의 복잡도는 O(min(len(dict), min(len(req)))입니다.Python의 자체적인 교차로 구현은 두 세트의 크기를 고려하기 때문에 최적의 것으로 보입니다.또한 c와 코어 라이브러리의 일부가 되는 것은 최적화되지 않은 대부분의 python 문보다 빠를 수 있습니다.따라서 제가 고려할 수 있는 솔루션은 다음과 같습니다.

dict = {'a':1,'b':2,'c':3,................................................}
req = ['a','c','w',...................]

{k:dic[k] for k in set(req).intersection(dict.keys())}

python의 c 코드 내부로 중요한 작업을 이동하며 모든 경우에 작동합니다.

처음 몇 가지 아이템을 원하는 경우n사전의 키를 모르는 경우:

n = 5 # First Five Items
ks = [*dikt.keys()][:n]
less_dikt = {i: dikt[i] for i in ks}

언급URL : https://stackoverflow.com/questions/5352546/extract-a-subset-of-key-value-pairs-from-dictionary

반응형