python - 使用列表推导创建指定的字典列表
问题描述
我有字典列表:
test_users = [{'user': 'ADMIN0', 'privilege': 'ADMIN', 'auth_protocol': 'SHA_512'},
{'user': 'ADMIN1', 'privilege': 'ADMIN', 'auth_protocol': 'SHA_256'}, \
{'user': 'MONITOR12', 'privilege': 'MONITOR', 'auth_protocol': 'SHA_512'}, \
{'user': 'MONITOR13', 'privilege': 'MONITOR', 'auth_protocol': 'SHA_256'}]
并想创建一个包含“特权”和“auth_protocol”唯一值的字典的新列表。例如:
selected_users= [{'user': 'ADMIN0', 'privilege': 'ADMIN', 'auth_protocol': 'SHA_512'},
{'user': 'MONITOR13', 'privilege': 'MONITOR', 'auth_protocol': 'SHA_256'}, \
限制:
1.'特权'永远不能被复制,
2.(可选)“auth_protocol”只有在使用所有可能性时才能重复(在这种情况下,它可以是“SHA_256”或“SHA_512”中的“auth_protocol”的另一个特权)
我尝试解决问题:
test_users_copy = test_users
selected_users = []
random_user = random.choice(test_users_copy)
# Add randomly chosen user to the list
selected_users.append(random_user)
test_users_copy.remove(random_user)
for test in selected_users:
selected_users += [user for user in test_users_copy if (user.get('privilege') not in test.get('privilege')) and (user.get('auth_protocol') not in test.get('auth_protocol'))]
解决方案
如果只想选择privilege
s 和auth_protocol
s 不同的用户:
>>> test_users = [{'user': 'ADMIN0', 'privilege': 'ADMIN', 'auth_protocol': 'SHA_512'},
... {'user': 'ADMIN1', 'privilege': 'ADMIN', 'auth_protocol': 'SHA_256'},
... {'user': 'MONITOR12', 'privilege': 'MONITOR', 'auth_protocol': 'SHA_512'},
... {'user': 'MONITOR13', 'privilege': 'MONITOR', 'auth_protocol': 'SHA_256'}]
>>> privileges, auth_protocols = set(), set()
>>> [tu for tu in test_users if not (tu["privilege"] in privileges or tu["auth_protocol"] in auth_protocols) and not privileges.add(tu["privilege"]) and not auth_protocols.add(tu["auth_protocol"])]
[{'user': 'ADMIN0', 'privilege': 'ADMIN', 'auth_protocol': 'SHA_512'}, {'user': 'MONITOR13', 'privilege': 'MONITOR', 'auth_protocol': 'SHA_256'}]
列表理解非常简单:如果看到tu["privilege"]
或tu["auth_protocol"]
,跳过字典;否则将它们添加到看到的权限和 auth_protocols (not x.add(y)
总是True
:这是在列表理解中可以接受副作用的极少数情况之一)。
但是,如果您没有不同的协议,这不会按特权返回字典。更糟糕的是,选择总是一样的。
要坚持您的可选要求,您需要更复杂的东西。
让我们构建一个 dict privilege -> auth_protocol -> users
:
>>> users_by_ap_by_privilege = {}
>>> for tu in test_users:
... users_by_ap_by_privilege.setdefault(tu["privilege"], {}).setdefault(tu["auth_protocol"], []).append(tu)
>>> users_by_ap_by_privilege
{'ADMIN': {'SHA_512': [{'user': 'ADMIN0', 'privilege': 'ADMIN', 'auth_protocol': 'SHA_512'}], 'SHA_256': [{'user': 'ADMIN1', 'privilege': 'ADMIN', 'auth_protocol': 'SHA_256'}]}, 'MONITOR': {'SHA_512': [{'user': 'MONITOR12', 'privilege': 'MONITOR', 'auth_protocol': 'SHA_512'}], 'SHA_256': [{'user': 'MONITOR13', 'privilege': 'MONITOR', 'auth_protocol': 'SHA_256'}]}}
我们希望每个用户privilege
(条件 1)和最大可能的不同auth_protocol
̀ s (条件 2)。
我们可以通过以下方式获得可用auth_protocol
的 s privilege
:
>>> ap_by_privilege = {privilege: users_by_ap.keys() for privilege, users_by_ap in users_by_ap_by_privilege.items()}
>>> ap_by_privilege
{'ADMIN': dict_keys(['SHA_512', 'SHA_256']), 'MONITOR': dict_keys(['SHA_512', 'SHA_256'])}
对于 Python < 3.6,我们需要为privilege
s 的所有顺序设置一次(在 Python >= 3.6 中不会造成任何伤害):
>>> privileges = list(ap_by_privilege)
>>> privileges
['ADMIN', 'MONITOR']
现在很容易构建auth_protocol
s 的所有组合:
>>> import itertools
>>> prod=list(itertools.product(*[ap_by_privilege[p] for p in privileges]))
>>> prod
[('SHA_512', 'SHA_512'), ('SHA_512', 'SHA_256'), ('SHA_256', 'SHA_512'), ('SHA_256', 'SHA_256')]
(请注意,元组包含与列表中的auth_protocol
每个关联的 s ,顺序相同)我们现在可以对每个组合影响重复计数:privilege
privileges
>>> import collections
>>> tuples_by_dup_count = {}
>>> for t in prod:
... tuples_by_dup_count.setdefault(max(collections.Counter(t).values()), []).append(t)
...
>>> tuples_by_dup_count
{2: [('SHA_512', 'SHA_512'), ('SHA_256', 'SHA_256')], 1: [('SHA_512', 'SHA_256'), ('SHA_256', 'SHA_512')]}
现在,我们取这个字典的最小键,即重复次数最少的元组(条件 2):
>>> ts = tuples_by_dup_count[min(tuples_by_dup_count)]
>>> ts
[('SHA_512', 'SHA_256'), ('SHA_256', 'SHA_512')]
然后我们选择auth_protocol
s的组合:
>>> import random
>>> t = random.choice(ts)
>>> t
('SHA_256', 'SHA_512')
并使用它通过privilege
/选择随机用户auth_protocol
:
>>> [random.choice(users_by_ap_by_privilege[p][t[i]]) for i, p in enumerate(privileges)]
[{'user': 'ADMIN0', 'privilege': 'ADMIN', 'auth_protocol': 'SHA_512'}, {'user': 'MONITOR13', 'privilege': 'MONITOR', 'auth_protocol': 'SHA_256'}]
推荐阅读
- powershell - Powershell脚本使用相同文件的前32个字符重命名文件夹内的文件
- reactjs - 反应:在 setInterval() 中访问多个状态 useEffect()
- javascript - Javascript:将非常大和非常小的数字转换为固定的人类可读字符串
- .net - VSTO 自定义功能区未显示
- python - 如何在python中用某些条件替换重复的数据框列值
- coinbase-api - Coinbase API - 购买和交易数据之间的关系 ID 问题
- python - 对象在python中没有属性
- python - 找到熊猫数据框中重复整数之间的最大位移的有效方法
- r - R testthat:仅在测试文件中使用外部包 - 而不是在说明中
- selenium - xUnit - 功能测试用数据打开浏览器实例的负载;在网址中