もう少し辞書型にこだわる
辞書型にこだわったが、もう少し考えた。
辞書型とリスト型も対応し、考え方はシンプルになる。
class Container():
data = None
def _dot2bra(self, path):
if '"' in path: return path
path = '["' + ( path.replace('].',']["').replace('.','"]["').replace('[','"][') + '"]' ).replace(']"]',']')
return path.replace('[""]','')
def _parse(self, path):
if path == '': return ''
path = self._dot2bra(path)
keys = path[1:-1].split('][')
for i,key in enumerate(keys): keys[i] = key.strip('"') if key[0]=='"' and key[-1]=='"' else int(key)
return keys
def _make_path(self, keys):
path = ''
for key in keys: path += ('[{}]' if type(key) is int else '["{}"]').format(key)
return path
def get_paths(self):
def _get_paths(data):
paths = []
if type(data) is dict:
for k, v in data.items():
paths.append('["{}"]'.format(k))
for path in _get_paths(v): paths.append('["{}"]{}'.format(k,path))
elif type(data) is list:
for k, v in enumerate(data):
paths.append('[{}]'.format(k))
for path in _get_paths(v): paths.append('[{}]{}'.format(k,path))
return paths
return _get_paths(self.data)
def exists_path(self, path):
try:
keys = self._parse(path)
data = self.data
for key in keys: data = data[key]
return True
except: return False
def get(self, path=''):
if path == '': return self.data
try:
#path = self._dot2bra(path)
#return eval('self.data{}'.format(path))
keys = self._parse(path)
data = self.data
for key in keys: data = data[key]
return data
except: return None
def set(self, value, path=''):
if path == '':
self.data = value
return True
try:
path = self._dot2bra(path)
exec('self.data{} = value'.format(path))
return True
except: return False
def add(self, value, path=''):
try: keys = self._parse(path)
except: return False
for i in range(len(keys)-1):
path = self._make_path(keys[:i+1])
try: data = eval('self.data{}'.format(path))
except: pass
try:
if type(keys[-1]) is int: eval('self.data{}.append(value)'.format(path))
else: eval('self.data{}.update({{"{}":value}})'.format(path, keys[-1]))
return True
except: return False
def pop(self, path):
keys = self._parse(path)
key = keys.pop()
path = self._make_path(keys)
try:
data = eval('self.data{}'.format(path))
if type(data) is dict:
value = data[key]
del data[key]
return value
elif type(data) is list: return data.pop(key)
except: return None
2020/07/29 05:45