python中基于字典值返回键的快速方法
我有两本字典:python中基于字典值返回键的快速方法,python,python-2.7,Python,Python 2.7,我有两本字典: dict1 = agent_id:agent_email dict2 = user_id:agent_id 我想创建一个字典: agent_id: list of user_ids associated with agent_id 如何从dict1中搜索dict2中的每个代理id并返回关联的密钥?有人告诉我,创建一个键列表,然后进行搜索是非常缓慢的。有没有更快的办法 这个被当作傻瓜提的问题并没有告诉我我想知道什么。我正在尝试搜索所有值,而不创建单独的列表。还有,一旦我有了值,
dict1 = agent_id:agent_email
dict2 = user_id:agent_id
我想创建一个字典:
agent_id: list of user_ids associated with agent_id
如何从dict1中搜索dict2中的每个代理id并返回关联的密钥?有人告诉我,创建一个键列表,然后进行搜索是非常缓慢的。有没有更快的办法
这个被当作傻瓜提的问题并没有告诉我我想知道什么。我正在尝试搜索所有值,而不创建单独的列表。还有,一旦我有了值,我如何获得相应的键
编辑
我需要的所有信息都在第2条中。问题是我如何做到这一点。每个代理id都与多个用户id相关联。我想创建一个如下所示的dict:
{agent_id_1:(user_id_1, user_id_2, user_id_45), agent_id_2:(user_id_987), agent_id_3:(user_id_10, user_id_67)...etc}
根据其中一个答案,我正在研究创建一个“反向dict”。我还不太明白这一点,因为dict2(代理ID)中的值不是唯一的。这是要走的路吗?试试这个
for key1, val1 in dict1.iteritems():
for key2,val2 in dict2.iteritems():
if key1 == val2:
print key2
如果这些值是唯一的(即,从“agent_id”开始,我假设没有重复),最简单的方法是维护两个字典。原始的一个和第二个,其中键是第一个的值,其值是第一个的索引。这种方式的查找几乎是即时的(仅在创建哈希时)
如果值中出现重复,除了搜索外,几乎无法执行其他操作。同样,如果您使用值维护一个树状结构,并指向键,则速度会更快。让我们开始为您的dict命名一些更具描述性的名称:
agent_id_to_email = agent_id: agent_email
user_to_agent_id = user_id: agent_id
现在,您需要所有user\u id
s从user\u到\u agent\u id
,以便agent\u id
位于agent\u id\u to\u email
中的有效密钥中
直接迭代和查找方法
时间复杂度:用户到代理id的大小近似线性
for user_id in (user_id
for user_id, agent_id in user_to_agent_id.iteritems()
if agent_id in agent_id_to_email
):
# do something
这在len(user\u to\u agent\u id)
中是时间线性的,因为我们迭代了它的所有项。代理id to_电子邮件查找中的代理id应该是近似恒定的(dict
s是哈希表),或者在最坏的情况下O(nx ln(n))
。由于这两个词典的大小似乎大致相同,所以无论n
是否超过user\u to\u agent\u id
或agent\u id\u to\u email
。如果与user\u-to\u-agent\u-id
相比agent\u-to\u-email
较小,则反向字典方法会更有效,但就目前情况而言,这是最好的方法
另请注意,集合交叉点似乎有一个O(N)
使用此SO问题的答案,我使用以下代码:
def dbwInvUserIdAgentId(dbwUserWithAgentD):
""" return dict of agents: user_id; only agents with
users and only one use per agent
so this inverts the dict
arguments:
dbwUserWithAgentD = dict of pure user_id: agent: id"""
return {v:k for k, v in dbwUserWithAgentD.iteritems()}
def dbwAgentUserIdsListD(dbwInvUserIdAgentId, dbwUserWithAgentD):
return_dict = {}
for agent_id in dbwInvUserIdAgentId:
temp_list = []
for k, v in dbwUserWithAgentD.iteritems():
if agent_id == v:
temp_list.append(k)
return_dict[agent_id] = temp_list
return return_dict
有cs背景的人能告诉我这有多有效吗?有更好的办法吗?我花了很长时间试图应用其他答案所说的。我想我可能问得不太好
不管怎样,非常感谢您的回答。两个dict的大小是否可能重复?(即,预期的优化是否重要?哪个是较大的dict?)多久执行一次查找?@dhke dict较大。每人超过10000人,而且还在增长。速度很重要。在重复的情况下,您可以使用值:set(key)
dict进行反向查找。此解决方案的优点是不消耗额外空间。不幸的是,它的时间复杂度为O(n²)——对于大型dict来说,它变得非常慢。如果我们首先构建一个反向dict(O(n)空间和时间复杂度),那么获得一个所有匹配项的列表只需要花费O(n)时间复杂度,这给了我们O(n)总体。我估计反向dict方法会更快,即使dict每个只包含20个左右的元素。@amon什么是反向dict方法?反向映射概念:map={a':1,'b':2}反向映射={1:'a',2:'b'}这可以作为反向映射={val:key for key,val in map.items()}假设字典查找是固定时间,这只剩下for循环的时间dbwAgentUserIdsListD()
嵌套两个循环,因此为O(n²)。另请注意,当原始映射不是1:1时,dbwInvUserIdAgentId()
会失败。@dhke非常感谢您对这个问题的关注。正在反转的dict(dbwUserWithAgentD)绝对不是1:1。每个代理id都有许多与其关联的用户id。因此,我将反转视为排序过滤器,因此产生的反转将有一个完整的代理ID列表,我可以使用它来创建所需的dict。希望这是有意义的。我很想知道我哪里出了问题dbwInvUserIdAgentId
具有最后一个键。把{a':1,'b':1}
放进去,你会得到{1:'b'}
或者{1:'a'}
,这取决于原始dict的迭代顺序(未定义)。所以,是的,你得到了一个过滤器,但是一个行为未定义的过滤器。