티스토리 뷰

개요


트리(Tree)는 자료구조라는 컴퓨터 과학의 분야가 생기기 전부터 사용하였습니다. 스무고개 게임의 경우가 트리 자료구조라고 할 수 있습니다. '사과' 를 맞춘다고 했을 때 질문이 '동물입니까?'라고 물어보면 '아닙니다'라고 할 것이고 '과일 입니까?' 라고 물어보면 맞다고 할 것입니다.

 

 

'과일'이라고 했을 때 과일이 아닌 모든 것은 제외하고 생각 할 수 있습니다. 동물쪽으로 가서 코끼리나 고양이를 확인 하지 않아도 됩니다.

 

이 경우 자료구조로 Tree를 쓰면 전체를 확인 하는 것에 비해 속도가 빠를 것입니다.

Tree를 쓰면 내가 이미 타고온 반대쪽은 탐색을 하지 않아도 되기 때문에 속도가 O(log n)이 되는 것입니다. 여기에서 이진트리라면 O(log 2)가 될 것이고 삼진트리라면 O(log 3)이 될 것입니다.

 

 

또 하나의 예를 들어보겠습니다.

 

이런 트리가 있다고 가정 해봅시다. 경기도 광주시 오포읍을 찾아가려면 트리의 경우는

'경기'로 가서

'광주시'를 찾고

'오포읍'을 찾으면 됩니다.

'서울'에 무슨 구가 있던지 무슨 동이 있던지 전혀 신경을 쓸 필요가 없습니다.

반대로 위와 같은 list가 있다고 생각 해봅시다. 대부분의 자료는 위와 같이 list형태로 되어 있는 경우가 많습니다. db에 주소가 들어가 있으면 위와 같이 들어 있을 것입니다.

 

데이터가 위와 같이 4개 밖에 없다면 '경기도 광주시 오포읍'을 금방 찾겠지만 실제로 db에서 뒤져야 하는 row수는 8000개가 넘습니다. 도로명 주소로 바뀌면서 탐색할 레코드가 훨씬 많아졌습니다.

 

그래서 이렇게 계층으로 되어있고 그 데이터를 자주 찾을때는 tree에서 찾는게 빠릅니다.

구현


실제로 찾고 싶은 것은 읍면동이 아니고 '행정동코드'(add_code)입니다.

시도, 시군구, 읍면동으로 주소를 찾는 로직을 만들 때 주소가 list에 들어있으면 한번 실행하는 속도가 O(n)입니다.

그런데 주소는 읍면동만 해도 8천개인데 가공해야 하는 row수가 100만개씩 되고 하면 속도가 아주 느릴 수 밖에 없습니다.

그래서 O(n)을 O(3)으로 줄이려고 아래 로직을 짰습니다.

 

아래 사이트에 들어가면 최신 법정동 행정동 매핑 파일을 받을 수 있습니다.

www.mois.go.kr/frt/bbs/type001/commonSelectBoardList.do?bbsId=BBSMSTR_000000000052

 

저는 '주민등록 주소 코드 변경 (2020. 8. 14. 시행 )'파일로 했습니다. jscode20200814(말소코드포함).zip [ 4.3 MB ] 이 파일을 받아서 KIKmix.20200814(말소코드포함) 에서 행정동 법정동 코드를 adm_code_law_code.csv로 바꾸어서 사용했습니다.

adm_code_law_code.csv
1.12MB

사용한 파일을 첨부합니다.

이런식으로 생겼습니다. adm_code는 행정동 코드이고 law_code는 법정동 코드 입니다.

 

import json

def make_tree(adm_law_codes):
    tre = {}
    for i in range(len(adm_law_codes)):
        spl = adm_law_codes[i].replace('\n','').split(',')
        # spl에서 2개 3개 나머지를 자른다.
        fst = spl[1][:2]
        snd = spl[1][2:5]
        trd = spl[1][5:]

        print(fst, snd, trd, type(fst))
        if tre.get(fst) == None:
            tre[fst] = {}
        if tre[fst].get(snd) == None:
            tre[fst][snd] = {}
        if tre[fst].get(snd).get(trd) == None:
            tre[fst][snd][trd] = spl[0]

    return tre

adm_law_codes = open('libs/adm_code_law_code.csv').readlines()[1:]
tre = make_tree(adm_law_codes)
open('tree_law_adm.json', 'w+').write(json.dumps(tre))

데이터 개수가 몇개 없으면 그냥 list 자료구조를 쓰면 되지만 바꿔야 할 주소는 여러개라서 tree로 짰습니다.

 

 

법정동코드 -> 행정동코드로 바꾸는 function예제

law_codes = json.loads(open('addr_codes.json').read())
dic = json.loads(open('tree_law_adm.json').read())
err_cnt = 0

def get_adm_code(law_code):
    try:
        f = law_code[:2]
        s = law_code[2:5]
        t = law_code[5:]
        adm_code = dic[f][s][t]
        return adm_code
    except Exception as e:
        print('error---', law_code)
        return None

for i in range(len(law_codes)):
    law_code = law_codes[i]
    adm_code = get_adm_code(law_code)
    if adm_code == None:
        err_cnt += 1
        print(law_code)
    else:
        print(adm_code)

print('err cnt:', err_cnt)

get_adm_code()에 law_code를 넣으면 adm_code를 return해줍니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함