列表理解和扁平化深层数据结构
List comprehension and flattening deep data structure
假设我有一个如下所示的数据结构(这已大大简化,我的实际数据在每个日期的每个作业都有大量特定于日期的数据):
data = {
'2019-01-01': {
'job-1-id': {'name': 'Job 1', 'address': '123 main st.'},
'job-2-id': {'name': 'Job 2', 'address': '824 1st Ave.'},
},
'2019-01-02': {
'job-1-id': {'name': 'Job 1', 'address': '123 main st.'},
'job-3-id': {'name': 'Job 3', 'address': '485 Pleasant Rd.'}
}
}
我想做的是将其展平,将 date
和 job id
推到一个对象数组中。例如:
data_flat = [
{'id': 'job-1-id', 'date': '2019-01-01', 'name': 'Job 1', 'address': '123 main st.'},
{'id': 'job-2-id', 'date': '2019-01-01', 'name': 'Job 2', 'address': '824 1st Ave.'},
{'id': 'job-1-id', 'date': '2019-01-02', 'name': 'Job 1', 'address': '123 main st.'},
{'id': 'job-3-id', 'date': '2019-01-02', 'name': 'Job 3', 'address': '485 Pleasant Rd.'},
]
显然我可以查看并构建一个新数组:
data_flat = []
for date, jobs in data.items():
for job_id, job in jobs.items():
data_flat.append({'id': job_id, 'date': date, etc...})
但是有没有更多的 pythonic/efficient 方法来使用列表理解和嵌套数据来做到这一点?我能想到的就是对内部循环使用列表理解,然后使用 extend
构建列表而不是附加。想法?
一个可能的列表理解解决方案如下,我们解压 job
字典并添加 id
和 date
key-value 对,同时迭代两个 for 循环
[{**job, 'id': job_id, 'date': date} for date, jobs in data.items() for job_id, job in jobs.items()]
在传统 for-loop 中,看起来像
for date, jobs in data.items():
for job_id, job in jobs.items():
data_flat.append({**job, 'id': job_id, 'date': date})
平面列表可以通过reduce
轻松制作。
所有你需要使用 initializer - reduce
函数中的第三个参数。
reduce(
lambda _list, date: _list.extend(
{'date': date, 'id':_id, **detail} for _id, detail in data[date].items()) or _list,
data,
[])
以上代码适用于 python2 和 python3,但您需要将 reduce 模块导入为 from functools import reduce
。详情请参阅下文link。
假设我有一个如下所示的数据结构(这已大大简化,我的实际数据在每个日期的每个作业都有大量特定于日期的数据):
data = {
'2019-01-01': {
'job-1-id': {'name': 'Job 1', 'address': '123 main st.'},
'job-2-id': {'name': 'Job 2', 'address': '824 1st Ave.'},
},
'2019-01-02': {
'job-1-id': {'name': 'Job 1', 'address': '123 main st.'},
'job-3-id': {'name': 'Job 3', 'address': '485 Pleasant Rd.'}
}
}
我想做的是将其展平,将 date
和 job id
推到一个对象数组中。例如:
data_flat = [
{'id': 'job-1-id', 'date': '2019-01-01', 'name': 'Job 1', 'address': '123 main st.'},
{'id': 'job-2-id', 'date': '2019-01-01', 'name': 'Job 2', 'address': '824 1st Ave.'},
{'id': 'job-1-id', 'date': '2019-01-02', 'name': 'Job 1', 'address': '123 main st.'},
{'id': 'job-3-id', 'date': '2019-01-02', 'name': 'Job 3', 'address': '485 Pleasant Rd.'},
]
显然我可以查看并构建一个新数组:
data_flat = []
for date, jobs in data.items():
for job_id, job in jobs.items():
data_flat.append({'id': job_id, 'date': date, etc...})
但是有没有更多的 pythonic/efficient 方法来使用列表理解和嵌套数据来做到这一点?我能想到的就是对内部循环使用列表理解,然后使用 extend
构建列表而不是附加。想法?
一个可能的列表理解解决方案如下,我们解压 job
字典并添加 id
和 date
key-value 对,同时迭代两个 for 循环
[{**job, 'id': job_id, 'date': date} for date, jobs in data.items() for job_id, job in jobs.items()]
在传统 for-loop 中,看起来像
for date, jobs in data.items():
for job_id, job in jobs.items():
data_flat.append({**job, 'id': job_id, 'date': date})
平面列表可以通过reduce
轻松制作。
所有你需要使用 initializer - reduce
函数中的第三个参数。
reduce(
lambda _list, date: _list.extend(
{'date': date, 'id':_id, **detail} for _id, detail in data[date].items()) or _list,
data,
[])
以上代码适用于 python2 和 python3,但您需要将 reduce 模块导入为 from functools import reduce
。详情请参阅下文link。