상세 컨텐츠

본문 제목

dict

Python

by techbard 2025. 1. 5. 21:28

본문

반응형

 

# Adding items to a dictionary
# ============================
# That's what the documentation means, when it says that dictionaries preserve the insertion
# order.
#
# As I've mentioned, if you're using Python version 3.5 or earlier, you'll get the entries
# appearing in random order. Prior to Python 3.6, dictionaries were unordered.
# You couldn't rely on the order of the keys, when iterating over the dictionary.

 

## dict 생성 방법들

d1 = {}
print(f'd1 => {type(d1)}')
print('=' * 30)

d2 = {'x':10, 'y':20}
print(f'd2 => {d2}')
print('=' * 30)

d3 = dict(x=10, y=20)
print(f'd3 => {d3}')
print('=' * 30)

d4 = {k : 0 for k in ('x', 'y')} # dict comprehension
print(f'd4 => {d4}')
print('=' * 30)

d5 = dict(zip(['x', 'y'], [10, 20]))
print(f'd5 => {d5}')
print('=' * 30)

d6 = dict([('x', 10), ('y', 20)])
print(f'd6 => {d6}')
print('=' * 30)

d7 = dict.fromkeys(['x', 'y'], 0)
print(f'd7 => {d7}')
print('=' * 30)

# 결과
d1 => <class 'dict'>
==============================
d2 => {'x': 10, 'y': 20}
==============================
d3 => {'x': 10, 'y': 20}
==============================
d4 => {'x': 0, 'y': 0}
==============================
d5 => {'x': 10, 'y': 20}
==============================
d6 => {'x': 10, 'y': 20}
==============================
d7 => {'x': 0, 'y': 0}
==============================

 

# Remember that len gives you the number of items in a collection.
# So, in the case of strings, len gives us the number of characters
# in that string.
# Len also works with dictionaries.
# So, if we pass in the dictionary inventory,
# thenwhen we call len on it,
# gives us the number of key-value pairs in the dictionary.

inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217}
print(f'Before bananas: {inventory['bananas']}')
inventory['bananas'] = inventory['bananas'] + 200
print(f'After bananas: {inventory['bananas']}')
numItems = len(inventory)
print(numItems)
inventory.update({'bananas': 777})
print(inventory)

# 결과
Before bananas: 312
After bananas: 512
4
{'apples': 430, 'bananas': 777, 'oranges': 525, 'pears': 217}

 

# Python dict = Java's HashMap

# Python 3's dict.keys() doesnt actually quite return
# a list directly.
# It returns something that we can actually iterate over,
# so we can put dict.keys() in our for loop
# but in order to actually get a list of keys we're always
# going to have to cast it to a list by calling the list function.

inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217}

for key in inventory:
    print("Get key", key, "that maps to", inventory[key])

# 또한, dict.items()의 결과가 (k, v) tuple이기 때문에 언패킹에 의해서
# for loop 문을 통해 k, v로 할당되는 것이다.

print(inventory.get("apples")) # == inventory["apples"]
# dict.get() 함수는 key가 존재하지 않아도 에러 내지 않고 None을 리턴한다.

# 결과
Get key apples that maps to 430
Get key bananas that maps to 312
Get key oranges that maps to 525
Get key pears that maps to 217
430

 

# 숫자가 키인 dict의 생성

fs = ['apple', 'banana', 'cherry']

df1 = dict(zip(range(len(fs)), fs))
print(f'df1 => {df1}')

print('*' * 40)

df2 = {}
for i, f in enumerate(fs):
    df2[i] = f
print(f'df2 => {df2}')

print('*' * 40)

df3 = {i : f for i, f in enumerate(fs)}
print(f'df3 => {df3}')

# 결과
df1 => {0: 'apple', 1: 'banana', 2: 'cherry'}
****************************************
df2 => {0: 'apple', 1: 'banana', 2: 'cherry'}
****************************************
df3 => {0: 'apple', 1: 'banana', 2: 'cherry'}

 

# Dictionary keys must be hashable
# : Same as with sets, dictionary keys must be hashable
# - hashable - immutable: int, float, boolean, str, tuple
# - UNhashable - mutable: list, set, dictionary
# : Dictionary values can be anything

# Create city coordinates with tuple as keys
cc = {
    (30, 95): 'Houston',
    (30, 85): 'New Orleans',
    (40, 80): 'New York',
    999: 'None'
    }

print(cc)

# 결과
{(30, 95): 'Houston', (30, 85): 'New Orleans', (40, 80): 'New York', 999: 'None'}

 

# dict 키-값의 조작

k = ['x', 'y']
v = [0, 0, 0]

d1 = dict(zip(k, v))
d1.setdefault('z', 0) # 키-값 쌍 추가
print(f'setdefault -> {d1}')
print('*' * 40)

d2 = dict(zip(k, v))
d2.update(x=1) # 키의 값 수정, 키가 없으면 키-값 쌍 추가
print(f'update -> {d2}')
print('*' * 40)

d3 = dict(zip(k, v))
d3.pop('y')
print(f'pop -> {d3}')
print('*' * 40)

d4 = dict(zip(k, v))
d4.update(x=100)
value = d4.get('x', 0)
print(f'get -> value of key "x": {value}')
print('*' * 40)

d5 = dict(zip(k, v))
d5['x'] = 99
print(f'assign -> {d5['x']}')
print('*' * 40)

# 결과
setdefault -> {'x': 0, 'y': 0, 'z': 0}
****************************************
update -> {'x': 1, 'y': 0}
****************************************
pop -> {'x': 0}
****************************************
get -> value of key "x": 100
****************************************
assign -> 99
****************************************

 

### dict 요소 조작 #2

def main():
    items = ['apple', 'banana']
    # 숫자를 dict key로 쓰기 위한 방법
    d = dict(zip(range(len(items)), items))

    d[len(items)] = 'strawberry' # 배열 인덱스로 dict 추가

    dt = {len(d):'lime'} # 임시 dict 생성
    d.update(dt) # 기존 dict에 임시 dict 추가

    print(d)

    print('\t')

    # Python 3.9에 추가된 dict merge, update
    # dict union 연산자

    d0 = {0:'apple'}
    d1 = {1:'peach'}

    ds01 = d0 | d1
    print('d0 | d1 ->', ds01)

    # 머지 순서 지켜짐 (Python 3.7 이상부터)
    ds10 = d1 | d0
    print('d1 | d0 ->', ds10)

    print('\t')

    # dict update 연산자

    d3 = {3:'pineapple'}
    d4 = {3:'tomato'}

    d3 |= d4
    print(d3)

    print('\t')

    d3 |= {3:'grape'}
    print(d3)

    pass

if __name__ == '__main__':
    main()
 
 #결과
 
 {0: 'apple', 1: 'banana', 2: 'strawberry', 3: 'lime'}
	
d0 | d1 -> {0: 'apple', 1: 'peach'}
d1 | d0 -> {1: 'peach', 0: 'apple'}
	
{3: 'tomato'}
	
{3: 'grape'}

 

### dict 언패킹

def print_info(name, age, address):
    print('이름', name)
    print('나이', age)
    print('주소', address)

def main():
    d = {'name': '고길동', 'age': 45, 'address':
        '서울특별시 도봉구 쌍문동 2-2'}
    print(*d)

    print('\t')

    print_info(**d)

if __name__ == '__main__':
    main()

#결과
name age address
	
이름 고길동
나이 45
주소 서울특별시 도봉구 쌍문동 2-2

 

# dict에서 key와 value로 조회
birth_years = {1994: 'bill', 1969: 'emily', 1982: 'elizabeth', 2000: 'turner'}

print(f'bitrh_years: {birth_years.items()}')
print(f'key: elizabeth exist in birth_years?', end=' ') 
print('elizabeth' in birth_years)

print(f'value: elizabeth exist in birth_years.values()?', end=' ') 
print('elizabeth' in birth_years.values())

print(len(birth_years))

# 결과
bitrh_years: dict_items([(1994, 'bill'), (1969, 'emily'), (1982, 'elizabeth'), (2000, 'turner')])
key: elizabeth exist in birth_years? False
value: elizabeth exist in birth_years.values()? True
4

 

# Looping to find the average score
# - Print out average score for each student.

d = {'Adam': [90, 85, 88], "Penelope": [77, 97, 100, 45],
    'Niko': [99, 45, 85]}

# 일반적인 for-loop 사용
students_fl = {}
for k, v in d.items():
    students_fl[k] = int(sum(v) / len(v))
print(students_fl)

# dict comprehension 사용
students_dc = {k: int(sum(v)/len(v)) for k, v in d.items()}
print(students_dc)

print("")
print(f"Is the same result? {students_fl == students_dc}")

# 결과
{'Adam': 87, 'Penelope': 79, 'Niko': 76}
{'Adam': 87, 'Penelope': 79, 'Niko': 76}

Is the same result? True

 

# dict의 shallow copy
# 단, 중첩 dict의 경우는 복사가 아닌 참조가 된다.
id_value = {1: '1', 2: '1', 3: '1'}
another_id_value = id_value.copy()
another_id_value[1] = '0'
another_id_value[2] = '0'
another_id_value[3] = '0'

print(f'id_value: {id_value}')
print(f'copy & modify another_id_value: {another_id_value}')

# 결과
id_value: {1: '1', 2: '1', 3: '1'}
copy & modify another_id_value: {1: '0', 2: '0', 3: '0'}

 

# dict setdefault 메서드
# 키가 없어도 에러를 내지않고 키-밸류 생성
# 이미 키가 있으면 현재 밸류 유지
computers = {'Lenovo': 'ThinkPad', 'Microsoft': 'Surface Pro'}
computers.setdefault('Apple', 'MacBook')
print(f'first setdefault of MB: {computers['Apple']}')

computers.setdefault('Apple', 'MacBook Pro')
print(f'second setdefault to MB Pro: {computers['Apple']}')

# 결과
first setdefault of MB: MacBook
second setdefault to MB Pro: MacBook

 

# 두 개의 리스트로 dict 생성
l1 = ['a', 'b', 'c']
l2 = [1, 2, 3]

ld = {x:y for x, y in zip(l1, l2)}
print(ld)

# 세 개의 리스트로 dict 생성 (value는 list)
l3 = ['one', 'two', 'three']

lld = {x:[y, z] for x, y, z in zip(l1, l2, l3)}
print(lld)

# 결과
{'a': 1, 'b': 2, 'c': 3}
{'a': [1, 'one'], 'b': [2, 'two'], 'c': [3, 'three']}

 

# 두 개의 리스트로 dict 생성 (zip 쓰지 않고)
l1 = ['a', 'b', 'c']
l2 = [1, 2, 3]
d = {}

# zip을 안 쓰고 k:v 생성
idx = 0
for x in l1:
    d[x] = l2[idx]
    idx += 1

print(d)

# 결과
{'a': 1, 'b': 2, 'c': 3}

 

# pop and popitem methods
# - pop: pass it a key, remove the entire item, return the value
# - popitem: takes no arguments, removes and returns last item

d = {'a': 1, 'b': 2, 'c': 3}

print(f"last item is {d.popitem()}")
print(f"remove last item and remains: {d}")

# 결과
last item is ('c', 3)
remove last item and remains: {'a': 1, 'b': 2}

 

# Changing a value of value
d = {'a': 1, 'b': [11, 'xx', 33]}
print(f"original dict: {d}")

d['b'][0] = 'xx'
print(f"changing a first value of 'b': {d}")

d['b'][-1] = 'xx'
print(f"changing a last value of 'b': {d}")

# 결과
original dict: {'a': 1, 'b': [11, 'xx', 33]}
changing a first value of 'b': {'a': 1, 'b': ['xx', 'xx', 33]}
changing a last value of 'b': {'a': 1, 'b': ['xx', 'xx', 'xx']}

 

  • 예제
    • 컨테이너
# dict의 생성 #1d = dict()print(type(d))
결과)<class 'dict'>

# dict의 생성 #2

d = {}print(type(d))
결과)<class 'dict'>
# dictd의 생성 #3

dict = {}

dict['apple'] = 1

dict['lemon'] = 2

dict['peach'] = 3

 

print(dict)

 

결과)

{'apple': 1, 'lemon': 2, 'peach': 3}


# dictd의 생성 #4

d = dict(a = 'a', b = 'b')

 

print(d['a'])
결과)a

 

# dict는 고정된 순서를 보장하지 않는다. (실행할 때마다 순서는 바뀐다.)chars = {'name':'mike', 'age': '24', 'address':'san diego'}print(chars)
결과){'age': '24', 'name': 'mike', 'address': 'san diego'}
chars = {'name':'mike', 'age': '24', 'address':'san diego'}print(chars)
결과){'name': 'mike', 'age': '24', 'address': 'san diego'}
# dict() 함수를 이용해서 생성할 때는 key = 형식으로 인자를 준다.chars = dict(name = 'mike', age = '24', address = 'san diego')

print(chars)

 

결과){'age': '24', 'name': 'mike', 'address': 'san diego'}
# 변수명으로 다른 사전 요소 추가d = dict( three = 3, four = 4)dx = dict( one = 1, two = 2, **d )

 

print( dx )
결과){'three': 3, 'one': 1, 'four': 4, 'two': 2}
  • 요소 접근

# dict에서는 인덱스로 요소를 참조할 수 없다.

chars = dict(name = 'mike', age = '24', address = 'san diego')print(chars[0])
결과)KeyError: 0
# in 내장 키워드로 Key가 존재하는지 확인하기chars = dict(name = 'mike', age = '24', address = 'san diego')if 'name' in chars:print(chars['name'])
결과)mike
# 순회해서 Key 가져오고, Key를 통해 Value 가져오기chars = dict(name = 'mike', age = '24', address = 'san diego')for key in chars:print('key: ' + key, '| value: ' + chars[key])
결과)key: address | value: san diegokey: name | value: mikekey: age | value: 24
# items() 메쏘드를 이용해 순회하기chars = dict(name = 'mike', age = '24', address = 'san diego')for key, value in chars.items():print('key: ' + key, '| value: ' + value)
결과)key: name | value: mikekey: address | value: san diegokey: age | value: 24
# 또 다른 value 읽기 메쏘드 (키를 찾지 못해도 exception을 발생시키지 않는다.)d = dict(one = 1, two = 2)

 

 

print(d.get('one', 'default'))
결과)1
d = dict(two = 2)

 

print(d.get('one', 'default'))
결과)default
# dict 요소의 삭제d = dict( one = 1, two = 2 )
del d['one']print(d)
d.pop('two')

 

print(d)
결과){'two': 2}

 

{}
  • 언팩킹 된 사전을 다시 사전으로 묶기

# Key, Value를 가지고 사전으로 묶기

chars = dict(name = 'mike', age = '24', address = 'san diego')key = chars.keys()value = chars.values()chars_dupe = zip(key, value)print(dict(chars_dupe))
결과){'address': 'san diego', 'name': 'mike', 'age': '24'}
  • 사전 업데이트 하기
# 항목에 assign을 하는 경우 혼동을 방지하기 위해 update() 메쏘드를 제공하는 것으로 보임d = {    'name': 'mike',    'age': 33,    'address': 'LA'}

 

d.update({'name': 'mike', 'age': 33})print(d)

 

결과){'name': 'mike', 'address': 'LA', 'age': 33}

 

d.update({'name': 'mike', 'age': 34, 'address': 'LA'})print(d)
결과){'address': 'LA', 'age': 34, 'name': 'mike'}

 

### Dict 컴프리헨션

def main():
    f = ['apple', 'banana', 'lemon']
    c = [1, 2, 3]

    d = dict(zip(f, c)) ; print('d         ->', d)
    d1 = {f:c for f, c in d.items()} ; print('d1        ->', d1)
    d2 = {f:c + 1 for f, c in d.items()} ; print('d2 (d1+1) ->', d2)
    d3 = {f:c for f, c in d.items() if c == 3} ; print('d3 (c==3) ->', d3)
    d4 = {f:c for f, c in d.items() if f.startswith('a')} ; print('d4 (a***) ->', d4)

    pass

if __name__ == '__main__':
    main()

# 결과
d         -> {'apple': 1, 'banana': 2, 'lemon': 3}
d1        -> {'apple': 1, 'banana': 2, 'lemon': 3}
d2 (d1+1) -> {'apple': 2, 'banana': 3, 'lemon': 4}
d3 (c==3) -> {'lemon': 3}
d4 (a***) -> {'apple': 1}

 

 

 

 

 

  • 사전과 함수 인자를 이용한 트릭
def display(name, address):    print('My name is', name + '.')    print('I live in', address + '.')
d = {    'name': 'mike',    'address': 'LA'}
print(display(**d))
결과)My name is mike.I live in LA.
  • 소팅된 사전 얻기

# 내장함수 sorted()를 이용해 key로 소팅된 사전을 얻을 수 있다.

d = dict(one=1, two=2)


for k in sorted(d.keys()):    print(k, d[k])
결과)one 1

 

two 2
# value로 소팅된 사전 얻기d = dict(one=2, two=1)
for k in sorted(d, key=lambda x: d[x]):

 

    print(k, d[k])
결과)two 1

 

one 2

# dict.__missing__ 서브 클래싱

 

from collections import Iterable

 

class range_dict(dict):

def __missing__(self, key):

for k, v in self.items():

if isinstance(k, Iterable):

left, right = k

if left <= key < right:

return v

raise KeyError("cannot find {} in range_dict".format(key))

 

codes = range_dict({

(0, 10): 'red',

(10, 100): 'yellow',

(100, 1000): 'green'

})

 

print(codes[99])

 

# 결과

yellow

 

# dict.__missing__ 을 이용한 passthru

 

class passthrudict(dict):

def __missing__(self, key):

return key

 

censor = passthrudict({

'hell': 'h***',

'darn': 'd*rn'

})

 

sentence = "That darn cat!"

 

print(' '.join(censor[w] for w in sentence.split()))

 

# 결과

That d*rn cat!

 

# dict를 이용한 count

 

ls = list(range(100))

 

def concordance(list):

freq = {}

 

for l in list:

if l not in freq:

freq[l] = 0

freq[l] += 1

return freq

 

print(concordance(ls))

 

# 결과

{0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1, 10: 1, 11: 1, 12: 1, 13: 1, 14: 1, 15: 1, 16: 1, 17: 1, 18: 1, 19: 1, 20: 1, 21: 1, 22: 1, 23: 1, 24: 1, 25: 1, 26: 1, 27: 1, 28: 1, 29: 1, 30: 1, 31: 1, 32: 1, 33: 1, 34: 1, 35: 1, 36: 1, 37: 1, 38: 1, 39: 1, 40: 1, 41: 1, 42: 1, 43: 1, 44: 1, 45: 1, 46: 1, 47: 1, 48: 1, 49: 1, 50: 1, 51: 1, 52: 1, 53: 1, 54: 1, 55: 1, 56: 1, 57: 1, 58: 1, 59: 1, 60: 1, 61: 1, 62: 1, 63: 1, 64: 1, 65: 1, 66: 1, 67: 1, 68: 1, 69: 1, 70: 1, 71: 1, 72: 1, 73: 1, 74: 1, 75: 1, 76: 1, 77: 1, 78: 1, 79: 1, 80: 1, 81: 1, 82: 1, 83: 1, 84: 1, 85: 1, 86: 1, 87: 1, 88: 1, 89: 1, 90: 1, 91: 1, 92: 1, 93: 1, 94: 1, 95: 1, 96: 1, 97: 1, 98: 1, 99: 1}

 

# collections - Counter

 

from collections import Counter

 

ls = list(range(100))

 

print(Counter(ls))

 

# 결과

Counter({0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1, 10: 1, 11: 1, 12: 1, 13: 1, 14: 1, 15: 1, 16: 1, 17: 1, 18: 1, 19: 1, 20: 1, 21: 1, 22: 1, 23: 1, 24: 1, 25: 1, 26: 1, 27: 1, 28: 1, 29: 1, 30: 1, 31: 1, 32: 1, 33: 1, 34: 1, 35: 1, 36: 1, 37: 1, 38: 1, 39: 1, 40: 1, 41: 1, 42: 1, 43: 1, 44: 1, 45: 1, 46: 1, 47: 1, 48: 1, 49: 1, 50: 1, 51: 1, 52: 1, 53: 1, 54: 1, 55: 1, 56: 1, 57: 1, 58: 1, 59: 1, 60: 1, 61: 1, 62: 1, 63: 1, 64: 1, 65: 1, 66: 1, 67: 1, 68: 1, 69: 1, 70: 1, 71: 1, 72: 1, 73: 1, 74: 1, 75: 1, 76: 1, 77: 1, 78: 1, 79: 1, 80: 1, 81: 1, 82: 1, 83: 1, 84: 1, 85: 1, 86: 1, 87: 1, 88: 1, 89: 1, 90: 1, 91: 1, 92: 1, 93: 1, 94: 1, 95: 1, 96: 1, 97: 1, 98: 1, 99: 1})

 

##table에 존재하는 문자열 패턴이 존재하는 것만 골라냄
##주의: dict.fromkeys 메서드가 원하는 결과가 나오지 않음
##https://ericssblog.wordpress.com/2017/11/04/dict-fromkeys-is-dangerous/

lookup_list = ['111', '010', '110']
match_list = ['1110000', '0010010', '010101101', '111110010']


def lookup_match(lookup, match):
    res_dict = {k : [] for k in lookup} # !!!
    for l in lookup:
        for m in match_list:
            if l in m:
                res_dict[l].append(m)
    return res_dict

ret = lookup_match(lookup_list, match_list)
print(ret)

# 결과
{'111': ['1110000', '111110010'], '010': ['0010010', '010101101', '111110010'], '110': ['1110000', '010101101', '111110010']}

## 이상한 dict.fromkeys()

key_list = ['a', 'b', 'c']

weird_d = dict.fromkeys(key_list, [])
print(f'init dict: {weird_d}')
print('*' * 50)
weird_d['a'].append(0)
print(f'after list appended: {weird_d}')
print('*' * 50)
weird_d['a'] = 1
print(f'after value assigned: {weird_d}')

# 결과
init dict: {'a': [], 'b': [], 'c': []}
**************************************************
after list appended: {'a': [0], 'b': [0], 'c': [0]}
**************************************************
after value assigned: {'a': 1, 'b': [0], 'c': [0]}

## 위의 결과를 보면 아주 이상하다.
## dict의 value에 list를 생성했는데, 그 list는 다 연결되어 있는 듯이
## 하나의 키에 value를 넣으면 모든 키 value에 같은 값이 들어간다.
## 위의 블로그에 소개 되어 있듯이 이뮤터블이 아닌 뮤터블을 value에 넣으면
## 모든 뮤터블이 공용처럼 작동한다.
## 블로그 저자는 그래서 fromkeys를 쓰지말고 dict 컴프리핸션을 쓰라고 권장한다.
## 이런 버그 아닌 스펙 아닌 현상 때문에 거의 2시간을 날렸다.

 

# 중복 값을 키로 재생성
ssn_name_pairs = {'123-456-789': 'John Appleseed',
                  '000-000-002': 'Dwight Schrute',
                  '999-000-005': 'Pam Beesly',
                  '888-888-888': 'John Appleseed',
                  '999-000-006': 'Pam Beesly',
                  '999-000-007': 'Pam Beesly'}

# {'Jone Appleseed': ['123-456-789', '888-888-888'],
# "Pam Beesly: ['999-000-005', '999-000-006', '999-000-007']}

def find_duplicate_names(ssn_name_dictionary: dict) -> dict:
    result_dict = {v : [] for v in ssn_name_dictionary.values()}
    for (k, v) in ssn_name_dictionary.items():
        result_dict[v].append(k)
    return result_dict

print(find_duplicate_names(ssn_name_pairs))

# 결과
{'John Appleseed': ['123-456-789', '888-888-888'], 'Dwight Schrute': ['000-000-002'], 'Pam Beesly': ['999-000-005', '999-000-006', '999-000-007']}

 

# dict를 사용해서 데이터 가공하기
fruits = ['apple', 'banana', 'cherry']
f_dict = {f : [] for f in fruits} # 매우 유용한 dict 컴프리핸션

for f in fruits:
    f_dict[f] = len(f)

print(f_dict)

# 결과
{'apple': 5, 'banana': 6, 'cherry': 6}

 

# 중첩 리스트를 가지고 kv dict를 생성해 데이터 정리
# isinstance(x, (int, float, complex)) and not isinstance(x, bool)

key_data = ['nums', 'alphas', 'fruits']
nl_dict = {k : [] for k in key_data} # {'nums': [], 'alphas': [], 'fruits': []}

nested_list = [[1, 2, 3], ['x', 'y', 'z'], ['apple', 'cherry']]

# index 순서대로 할당
# 인덱스 따지는 게 복잡하기는 하지만 순차 데이터면 타입 따지지 않고 사용 가능
if len(key_data) == len(nested_list):
    for k in key_data:
        nl_dict[k] = nested_list[key_data.index(k)]

# 각 요소의 타입에 따라 할당 (좀 복잡하고 딱히 범용적이지 않음)
# for nl in nested_list:
    # if isinstance(nl[0], int):
        # nl_dict['nums'] = nl
    # elif isinstance(nl[0], str) and len(nl[0]) == 1:
        # nl_dict['alphas'] = nl
    # else:
        # nl_dict['fruits'] = nl

print(nl_dict)

# 결과
{'nums': [1, 2, 3], 'alphas': ['x', 'y', 'z'], 'fruits': ['apple', 'cherry']}

 

# Nested Dictionaries extraction

info = {'personal_data':
         {'name': 'Lauren',
          'age': 20,
          'major': 'Information Science',
          'physical_features':
             {'color': {'eye': 'blue',
                        'hair': 'brown'},
              'height': "5'8"}
         },
       'other':
         {'favorite_colors': ['purple', 'green', 'blue'],
          'interested_in': ['social media', 'intellectual property', 'copyright', 'music', 'books']
         }
      }

color = info['personal_data']['physical_features']['color']

print(color)

# 결과
{'eye': 'blue', 'hair': 'brown'}

 

import json

a_string = '\n\n\n{\n "resultCount":25,\n "results": [\n{"wrapperType":"track", "kind":"podcast", "collectionId":10892}]}'

print(a_string)
d = json.loads(a_string)
print("=======================================")
print(type(d))
print(d.keys())
print(d['resultCount'])
print(d['results'][0]['collectionId']) # 리스트 내 요소가 1개 있고 그 요소는 dict이다.

# {
#  "resultCount":25,
#  "results": [{"wrapperType":"track", "kind":"podcast", "collectionId":10892}]
# }

# 결과
{
 "resultCount":25,
 "results": [
{"wrapperType":"track", "kind":"podcast", "collectionId":10892}]}
=======================================
<class 'dict'>
dict_keys(['resultCount', 'results'])
25
10892

 

import json

def pretty(obj):
    return json.dumps(obj, sort_keys=True, indent=2)

d = {'key1': {'c': 5, 'a': 90, '5': 50}, 'key2': {'b':3, 'c': 'yes'}}

print(d)
print('-----')
print(pretty(d))

# 결과
{
  "key1": {
    "5": 50,
    "a": 90,
    "c": 5
  },
  "key2": {
    "b": 3,
    "c": "yes"
  }
}

 

# Nested Iteration의 값을 dict로 정리
info = [['1', 10, 20, 30], ['2', 100, 200, 300], ['3', 1000, 2000, 3000]]
print(f'original data: {info}')

# keys = []
# for i in info:
    # keys.append(i[0])
keys = [i[0] for i in info]
print(f'create keys: {keys}')

d = {k : [] for k in keys}
print(f'create empty dict with keys: {d}')

for i in info:
    d[i[0]] = sum(i[1:])
print(f'ccomplete dict: {d}')

# 결과
original data: [['1', 10, 20, 30], ['2', 100, 200, 300], ['3', 1000, 2000, 3000]]
create keys: ['1', '2', '3']
create empty dict with keys: {'1': [], '2': [], '3': []}
ccomplete dict: {'1': 60, '2': 600, '3': 6000}

 

# Below, we have provided a nested list called big_list.
# Use nested iteration to create a dictionary, word_counts,
# that contains all the words in big_list as keys,
# and the number of times they occur as values.

# Its a little difficult to me.
# [[[ 에 주목

big_list = [[['one', 'two'], ['seven', 'eight']], [['nine', 'four'], 
['three', 'one']], [['two', 'eight'], ['seven', 'four']], 
[['five', 'one'], ['four', 'two']], [['six', 'eight'], 
['two', 'seven']], [['three', 'five'], ['one', 'six']], 
[['nine', 'eight'], ['five', 'four']], [['six', 'three'], ['four', 'seven']]]

# my solution
flattened_big_list = []

for outer_lst in big_list:
    if type(outer_lst) is list:
        for inner_lst in outer_lst:
            if type(inner_lst) is list:
                for e in inner_lst:
                    flattened_big_list.append(e)

keys = set(flattened_big_list)
d = {k : 0 for k in keys}

for e in flattened_big_list:
    d[e] += 1

print(d)

# best solution
word_counts = {}

for outer_lst in big_list:
    if type(outer_lst) is list:
        for inner_lst in outer_lst:
            if type(inner_lst) is list:
                for word in inner_lst:
                    if word in word_counts:
                        word_counts[word] += 1
                    else:
                        word_counts[word] = 1

print(word_counts)

# 결과
{'eight': 4, 'six': 3, 'nine': 2, 'three': 3, 'five': 3, 'seven': 4, 'two': 4, 'one': 4, 'four': 5}
{'one': 4, 'two': 4, 'seven': 4, 'eight': 4, 'nine': 2, 'four': 5, 'three': 3, 'five': 3, 'six': 3}

 

# file 읽기, 쓰기와 dict 누적의 사용
path = "C:\\Users\\...\\2024-11-07"
fn = "random_ints.txt"

import random

with open(path + "\\" + fn, "w") as fw:
    for i in range(10):
        fw.write(str(random.randint(0, i)))

int_count = {}

with open(path + "\\" + fn, "r") as fo:
    for i in fo.read():
        if int_count.get(i) == None:
            int_count[i] = 0
        else:
            int_count[i] += 1

print(int_count)

# 결과
{'0': 2, '1': 1, '2': 0, '4': 1, '5': 0, '3': 0}

 

# Accumulating Multiple Results In a Dictionary
# 매우 자주 사용되는 패턴
sentence = "The dog chased the rabbit into the forest but the rabbit was too quick."

words = sentence.split()

word_counts = {}

for word in words:
    if word not in word_counts:
        word_counts[word] = 0
    word_counts[word] += 1

print(word_counts)

# 결과
{'The': 1, 'dog': 1, 'chased': 1, 'the': 3, 'rabbit': 2, 'into': 1, 'forest': 1, 'but': 1, 'was': 1, 'too': 1, 'quick.': 1}

 

# Word Counter
words = "This document is a document of words. Words are important.".lower()
words = words.replace('.', '')

d = {}

for word in words.split():
    if word in d.keys():
        d[word] += 1
    else:
        d[word] = 1

print(d)

# 결과
{'this': 1, 'document': 2, 'is': 1, 'a': 1, 'of': 1, 'words': 2, 'are': 1, 'important': 1}

 

# Accumulating Results From a Dictionary
# Using standard accumulation pattern

travel = {"North America": 2, "Europe": 8, "South America": 3, 
        "Asia": 4, "Africa":1, "Antarctica": 0, "Australia": 1}

total = 0

for continent in travel:
    total += travel[continent]

print(total)

# 결과
19

 

# Accumulating the Best Key

placement = "Beaches are cool places to visit in spring however the Mackinaw Bridge is near. Most people visit Mackinaw later since the island is a cool place to explore."

d = {}

for c in placement:
    if c not in d:
        d[c] = 0
    d[c] += 1

keys = list(d.keys())
min_value = keys[0]

for key in keys:
    if d[key] < d[min_value]:
        min_value = key

print(f"min_value key is {min_value}")
print(f"min_value value is {d[min_value]}")

# 결과
min_value key is x
min_value value is 1

 

# type hint에서 | 은 두 가지 타입 모두 가능하다는 명시
users: dict = {1: 'a', 2: 'b'}
possible_user: str | None = users.get(3)
print(possible_user)
# ---> 키가 없어서 None 리턴했지만

users[3] = 'c'
possible_user: str | None = users.get(3)
print(possible_user)
# ---> 키가 생긴 이후 str 타입을 리턴했다.

# 결과
None
c

 

# 단순 리스트를 dict로 바꾸는 또 다른 방법

flavor_list: list[str] = ['vanilla', 'chocolate', 'pecan', 'strawberry']
flavor_idx_list: list[tuple[int, str]] = list(enumerate(flavor_list))
flavor_dict: dict[int, str] = {(idx, flavor) for (idx, flavor) in flavor_idx_list}
print(flavor_dict)

# 결과
{(3, 'strawberry'), (0, 'vanilla'), (1, 'chocolate'), (2, 'pecan')}

 

# In essence:
# This code demonstrates how to use a defaultdict with a custom default_factory 
# to automatically handle missing keys. The CountMissing class keeps track of 
# the number of times a default value was created, allowing you to monitor 
# the frequency of missing keys in your data.

# 좀 희안한 트릭인데, defaultdict에는 factory 클래스를 지정할 수 있게 되어 있음
# 매우 간단한 계수기 클래스를 지정함
# 그런데, defaultdict가 존재하지 않는 키를 만나면 factory를 호출함
# 따라서, 현재 가진 kv에 없는 kv를 만나면 factory가 호출되면서 계수가 됨
# 결국 최종 계수된 값은 현재 들고 있는 kv와 다른 kv의 개수를 가지게 됨

# from collections import defaultdict

# class CountMissing(object):
#     def __init__(self) -> None:
#         self.added = 0
    
#     def __call__(self) -> int:
#         self.added += 1
#         return 0

# counter = CountMissing()
# current = {'green':12, 'blue': 3}
# result = defaultdict(counter, current)
# increments = [('red', 5), ('blue', 17), ('orange', 9)]
# for key, offset in increments:
#     result[key] += offset

# print(counter.added)
# print(result)

# 결과
2
defaultdict(<__main__.CountMissing object at 0x0000024DC4C2B770>, {'green': 12, 'blue': 20, 'red': 5, 'orange': 9})
반응형

관련글 더보기

댓글 영역