nested dict+list, 재귀호출 관련
조회수 366회
맨 뒤에 질문 먼저 봐 주시면 감사하겠습니다.
from shapely.geometry import Point,LineString, Polygon
from shapely import affinity
from collections.abc import Iterable
from copy import deepcopy
ka={
'draw': [
{'deg': 225.0, 'layer': 'C1T1', 'obj': Polygon([[1,1],[2,2],[1,3]])},
{'deg': 222.2, 'layer': 'C1T1', 'obj': Polygon([[1,1],[2,2],[1,3]])},
{'deg': 228.0, 'layer': 'C1T1', 'obj': Polygon([[1,1],[2,2],[1,3]])},
{'deg': 225.2, 'layer': 'C1T1', 'obj': Polygon([[1,1],[2,2],[1,3]])},
{'deg': 90.0, 'layer': 'C1T1', 'obj': Polygon([[1,1],[2,2],[1,3]])},
{'deg': 44.0, 'layer': 'C1T1', 'obj': Polygon([[1,1],[2,2],[1,3]])},
{'deg': 314.9, 'layer': 'C1T1', 'obj': Polygon([[1,1],[2,2],[1,3]])},
{'deg': 225.1, 'layer': 'C1T1', 'obj': Polygon([[1,1],[2,2],[1,3]])}
],
'txt': [
{'deg': 90.0, 'layer': 'num', 'obj': LineString([[1,1],[2,2]]), 'txt': 566.0, 'type': 'num'},
{'deg': 90.0, 'layer': 'num', 'obj': LineString([[1,1],[2,2]]), 'txt': 102.0, 'type': 'num'},
{'deg': 90.0, 'layer': 'num', 'obj': LineString([[1,1],[2,2]]), 'txt': 668.0, 'type': 'num'},
{'deg': 0.0, 'layer': 'num', 'obj': LineString([[1,1],[2,2]]), 'txt': 672.0, 'type': 'num'},
{'deg': 0.0, 'layer': 'num', 'obj': LineString([[1,1],[2,2]]), 'txt': 566.0, 'type': 'num'},
{'deg': 0.0, 'layer': 'num', 'obj': LineString([[1,1],[2,2]]), 'txt': 1238.0, 'type': 'num'},
{'deg': 0.0, 'layer': 'num', 'obj': LineString([[1,1],[2,2]]), 'txt': 1140.0, 'type': 'num'},
{'deg': 0.0, 'layer': 'num', 'obj': LineString([[1,1],[2,2]]), 'txt': 98.0, 'type': 'num'},
{'deg': 18.5, 'layer': 'size-x', 'obj': LineString([[1,1],[2,2]]), 'txt': 1238.0, 'type': 'size-x'},
{'deg': 18.5, 'layer': 'size-y', 'obj': LineString([[1,1],[2,2]]), 'txt': 668.0, 'type': 'size-y'},
{'deg': 0.0, 'layer': 'no', 'obj': LineString([[1,1],[2,2]]), 'txt': '-01', 'type': 'no'}
],
'fence': LineString([[1,1],[2,2],[1,3]]),
'figure': LineString([[1,1],[2,2],[1,3]]),
'no': '-01',
'size-x': 1238.0,
'size-y': 668.0
}
def zoom_to_real(data):
r = deepcopy(data)
for ga, ka in data.items():
sx, sy = 5,5 # scale x,y 배율
for gb, kb in ka.items():
#r[ga][gb]=zoomall(ka,sx,sy)
if type(kb) in [Point,LineString, Polygon]:
r[ga][gb] = affinity.scale(kb, xfact=sx, yfact=sy, origin=(0, 0))
elif type(kb) == list:
_tmp = []
for kc in kb:
_dict = deepcopy(kc)
_dict['obj'] = affinity.scale(kc['obj'], xfact=sx, yfact=sy, origin=(0, 0))
_tmp.append(_dict)
r[ga][gb] = _tmp
return r
def zoomall(adata,sx,sy):
if isinstance(adata,dict):
return {g:zoomall(k,sx,sy) for g,k in adata.items()}
if isinstance(adata, Iterable):
return [zoomall(x,sx,sy) for x in adata]
if isinstance(adata, (Point,LineString,Polygon)):
_zoomed= affinity.scale(adata, xfact=sx, yfact=sy, origin=(0, 0))
return _zoomed
return adata
dict와 list가 중첩된 data dict가 있습니다.
첫번째 key의 value가 글 첫 머리에 있는 ka입니다.
코딩을 하면서 계속 고민인 것은 사용하는 dict는
지금의 구조(dict in dict+list)가 최대?깊이?이고요.
처리하는데에 매번 하드코딩?이라는 느낌이 들어서 이상해요.
중간에 zoom_to_real 함수에 있는 if-elif로 구현은 했지만
affinity.scale이 반복되는 것이 부담스러워서
스택오버플로우에서 발견한 재귀호출 예제를 조금 고쳐서
같은 기능을 하라고 r[ga][gb]=zoomall(ka,sx,sy)를 만들었습니다.
이 zoomall재귀호출 함수가 매우 작은 dict+list(둘 다 중첩된)에서 잘
작동하는데, 이번에는 dict가 깊고 커서 그런지
RecursionError: maximum recursion depth exceeded in comparison 에러가 나옵니다.
찾아보니 재귀호출 제한 횟수를 늘리는 방법이 있던데 위험한거 같아서 안하기로 하고 잊었구요.
질문을 정리하면,
dict가 2~3차원 dict이고. list도 있고 복잡한데, 그 구조를 유지하면서 내부를 돌아서
value가 type이 Point, LineString, Polygon일 경우 affinity.scale를 적용하고 싶습니다.
zoomall을 새로 만들어야 할 거 같은데 무엇을 알아야 하는지
재귀호출이 아닌 다른 것을 써야 하는지
키워드라도 좋으니 한마디 해주시면 정말 감사하겠습니다.
-
(•́ ✖ •̀)
알 수 없는 사용자
댓글 입력