我有一个list如下
[[['server', ''],['port','8800'],['location','/'],['location','/aa'],['location','bb']],[['server', ''],['port','80'],['location','/'],['location','/aa'],['location','bb']]]
想要得到如下的dict
[{'server': '','port': '8800','location': '/,/aa,/bb'},{'server': '','port': '80','location': '/,/aa,/bb'}]
或者
[{'server': '','port': '8800','location': '/'},{'server': '','port': '8800','location': '/aa'},{'server': '','port': '8800','location': '/bb'},{'server': '','port': '80','location': '/'},{'server': '','port': '80','location': '/aa'},{'server': '','port': '80','location': '/bb'}]
求解
之前有sf上的同学给出了一个例子
def turn2dic(lst):
global key, value
dic = {}
if all([not isinstance(item, list) for item in lst]):
if len(lst) == 2:
key, value = lst
elif len(lst) == 1:
key=lst[0]
value=''
elif len(lst) == 3:
key=lst[0]
value=lst[1]
dic[key] = value
else:
for item in lst:
subdic = turn2dic(item)
print subdic
dic.update(subdic)
print dic
return dic
但是这个上面代码里,location是覆盖的,因为dic.update(subdic),有什么办法是append的?
巴扎黑2017-04-17 17:56:02
def single_turn2dic(lst):
global key, value
dic = {}
if all([not isinstance(item, list) for item in lst]):
if len(lst) == 2:
key, value = lst
elif len(lst) == 1:
key = lst[0]
value = ''
elif len(lst) == 3:
key = lst[0]
value = lst[1]
# dic[key] = value
if value and dic.get(key, ''):
dic[key] += ',' + value
else:
dic[key] = value
else:
for item in lst:
subdic = single_turn2dic(item)
# print subdic
# dic.update(subdic)
for name, name_value in subdic.iteritems():
if name_value and dic.get(name, ''):
dic[name] += ',' + name_value
else:
dic[name] = name_value
# print dic
return dic
servers = [[['server', ''], ['port', '8800'], ['location', '/'], ['location', '/aa'], ['location', 'bb']],
[['server', ''], ['port', '80'], ['location', '/'], ['location', '/aa'], ['location', 'bb']]]
def beautify(servers):
# lst = []
if not isinstance(servers[0][0], list):
return single_turn2dic(servers)
else:
return [beautify(server) for server in servers]
print beautify(servers)
大致思路就是 [['server', ''], ['port', '8800'], ['location', '/'], ['location', '/aa'], ['location', 'bb']]
這種的視為一個單元處理(函數修改自你給的程式碼),遞歸到可以處理程度(因為層數可能不為2)
PHP中文网2017-04-17 17:56:02
代碼:
def turn2dic(lst):
dic = {}
if all([not isinstance(item, list) for item in lst]):
key, value = lst
dic[key] = value
else:
for item in lst:
subdic = turn2dic(item)
for key, value in subdic.items():
dic.setdefault(key, []).append(value)
return dic
results = [turn2dic(item) for item in lst]
print results
結果:
[{'location': ['/', '/aa', 'bb'], 'port': ['8800'], 'server': ['']}, {'location': ['/', '/aa', 'bb'], 'port': ['80'], 'server': ['']}]
我覺得不必要的程式碼可以拿掉,這次的問題既然比較單純(既然這次都確定底層是雙元素的list),那就不用做太多判斷和處理(甚至這個recursive 的解法也可以改成簡單的做法)。
我不確定你的資料裡面,除了location
以外還有沒有別的會重複的東西,我覺得統一處理比較好,所以我字典的值跟你給出的範例不太一樣,用list 而不是string 。
伊谢尔伦2017-04-17 17:56:02
分拆開來好看一點
from collections import defaultdict
def testtype(t):
return lambda x: isinstance(x, t)
def test(t, lst):
return all(map(t if callable(t) else testtype(t), lst))
def parse_dict(lst):
dct = defaultdict(lambda: [])
for k, v in lst:
dct[k].append(parse(v))
ret = {}
for k, v in dct.items():
if test(str, v):
v = ','.join(v)
elif len(v) == 1:
v = v[0]
ret[k] = v
return ret
def parse(obj):
if not isinstance(obj, list):
return obj
if test(lambda x: len(x) == 2, obj):
return parse_dict(obj)
return list(map(parse, obj))
src= [[['server', ''],['port','8800'],['location','/'],['location','/aa'],['location','bb']],[['server', ''],['port','80'],['location','/'],['location','/aa'],['location','bb']]]
print(parse(src))