给定一个类似的元组列表
[(1, 'Japan', 1, 'Tokyo'), (1, 'Japan', 2, 'Osaka'), (2, 'Korea', 1, 'Seoul',), (2, 'Korea', 2, 'Pyongyang')]
# country_id, country_name, city_id, city_name
我想把它构造成这样:
{
'countries': [
{
'country_id': 1,
'country_name': 'Japan',
'cities': [
{
'city_id': 1,
'city_name': 'Tokyo'
},
{
'city_id': 2,
'city_name': 'Osaka'
}
]
},
{
'country_id': 2,
'country_name': 'Korea',
'cities': [
{
'city_id': 1,
'city_name': 'Seoul'
},
{
'city_id': 2,
'city_name': 'Pyongyang'
}
]
}
]
}
我实现了这个,它运行得很好,但不是Python。想知道这是否可以大大改进/加速,因为这形成了API的响应。
x = [(1, 'Japan', 1, 'Tokyo'), (1, 'Japan', 2, 'Osaka'), (2, 'Korea', 1, 'Seoul'), (2, 'Korea', 2, 'Pyongyang')]
countrylist = []
query_countries = []
for a in x:
if a[0] not in countrylist:
query_countries.append((a[0], a[1]))
countrylist.append(a[0])
countrylist = list(set(countrylist))
countries = [{'country_id': r[0], 'country_name': r[1], 'cities': []} for r in query_countries]
for r in x:
countries[countrylist.index(r[0])]['cities'].append({'city_id': r[2], 'city_name': r[3]})
final = {'countries': countries}
print(final)
#{'countries': [{'country_id': 1, 'country_name': 'Japan', 'cities': [{'city_id': 1, 'city_name': 'Tokyo'}, {'city_id': 2, 'city_name': 'Osaka'}]}, {'country_id': 2, 'country_name': 'Korea', 'cities': [{'city_id': 1, 'city_name': 'Seoul'}, {'city_id': 2, 'city_name': 'Pyongyang'}]}]}
表达式a[0] not in countrylist
和countrylist.index(r[0])
不是最有效的,因为countrylist
是一个列表,这些操作需要扫描列表。在某个时刻,您可以将其转换为一个集合,但您可以决定从开始一直使用集合,然后这些查找操作可以在恒定的时间内(平均)完成。这已经可以提高大型输入的性能。
对于这种挑战,groupby
和itemgetter
似乎是很好的工具。他们允许用一个表达式来完成任务:
data = [(1, 'Japan', 1, 'Tokyo'), (1, 'Japan', 2, 'Osaka'), (2, 'Korea', 1, 'Seoul',), (2, 'Korea', 2, 'Pyongyang')]
from itertools import groupby
from operator import itemgetter
result = [
{
"country_id": country_id,
"country_name": country_name,
"cities": [
{
"city_id": city_id,
"city_name": city_name
} for *_, city_id, city_name in cities
]
} for (country_id, country_name), cities in groupby(data, itemgetter(0, 1))
]
print(result)
groupby
你可以想象这个groupby
调用返回这个结构:
[
(1, 'Japan'), [
(1, 'Japan', 1, 'Tokyo'),
(1, 'Japan', 2, 'Osaka')
],
(2, 'Korea'), [
(2, 'Korea', 1, 'Seoul'),
(2, 'Korea', 2, 'Pyongyang')
]
]
只是列表不是列表而是迭代器。但对于for ... in
语法来说,这并没有什么区别。
内部元组只是对原始数据的引用,而外层(组)中的值由itemgetter
生成,它生成前两个值的元组。