Python 如果值相同,则合并字典键

Python 如果值相同,则合并字典键,python,Python,所以这是一个奇怪的问题,我怀疑它很容易解决。我正在为家里的远程玩家构建一个歌词网络应用程序。它目前会生成一个玩家的字典,里面有他们正在播放的歌曲。例如: { 'bathroom': <Song: Blur - Song 2>, 'bedroom1': <Song: Blur - Song 2>, 'kitchen': <Song: Meat Loaf - I'd Do Anything for Love (But I Won't Do Tha

所以这是一个奇怪的问题,我怀疑它很容易解决。我正在为家里的远程玩家构建一个歌词网络应用程序。它目前会生成一个玩家的字典,里面有他们正在播放的歌曲。例如:

{
    'bathroom': <Song: Blur - Song 2>,
    'bedroom1': <Song: Blur - Song 2>,
    'kitchen': <Song: Meat Loaf - I'd Do Anything for Love (But I Won't Do That)>,
}
{
“浴室”:,
“卧室1”:,
“厨房”:,
}
偶尔会同步这些玩家的子集。因此,如上所述,它们显示相同的值我想在界面中对它们进行分组。我在构建字典时可能会更聪明,但假设我不会这样做,有没有一种按值合并键的好方法

从上面得到的期望输出如下:

{
    'bathroom,bedroom1': <Song: Blur - Song 2>,
    'kitchen': <Song: Meat Loaf - I'd Do Anything for Love (But I Won't Do That)>,
}
{
“浴室,卧室1”:,
“厨房”:,
}
然而,这确实打破了我想要查找事物的方式(我想通过名称来指定,因此这是一本字典)。。。是否有更好的集合可以为每个值提供多个键,并指示何时存在合并的重复项(并向后引用其所有键)


有一个很好的答案,它将此转换为一个歌曲键,并将播放器列表作为一个值。这是伟大的,除了有时我想知道哪首歌是在一个命名的播放器上播放。这就是我最初使用字典的原因


有没有一种好方法可以在两个方向上保留查找(除了保留两个集合)?

当所涉及的数据量很大时,这就是关系数据库方便使用的类型。具有两列(键和值)以及键列上的索引的数据库的行为有点像dict。但是您也可以在值列上放置索引以实现高效的反向查找

但是,在您的情况下,由于涉及的数据量很小,我只需要制作一个
defaultdict
,然后添加
(值、键)

reverse_lookup = defaultdict(list)
for k, v in now_playing.items():
    reverse_lookup[v].append(k)
然后您可以
,'.join()
这些值来生成复合键。由于这些组合键将用于显示,似乎并不是真正用于查找,所以我会将原始dict和反向查找dict都保留在内存中,并在需要执行查找时使用您需要的任意一个。查找与给定歌曲播放相同歌曲的其他播放器(可能是同步的)的任务涉及两个查找,一个正向查找,一个反向查找,但它们是哈希表查找,因此增加的成本最小


在考虑了其他更“有趣”的方法之后:你可能会为了满足你的需求而改变你的想法。每个播放器都有一个节点,当前播放的每首歌曲都有一个节点。节点按歌曲分组,其中一组包含歌曲的节点和当前播放该歌曲的任何播放机的节点。如果将每个集合的节点(歌曲加播放器)放在循环链接列表中,只要正确维护了整体数据结构,就可以从任何节点开始,遍历列表,在歌曲和播放该歌曲的播放器列表上进行迭代


当然,诀窍在于找到一种有效的方法来维护整个数据结构,即随着歌曲的变化更新循环列表。如果球员是真正的同步,这就像更换一个歌曲节点与另一个一样容易,每次整个组球员移动到下一个轨道。但我可以想象,像您正在构建的应用程序一样,经常需要执行其他类型的查找,而不相交集结构对您没有任何好处。

是的,这可能会奏效。我将不得不改变一些逻辑,但从歌曲而不是播放器的角度来思考问题实际上也可能解决一大堆其他问题。为什么不改变这种结构呢?因为歌曲是独一无二的,所以它可能是这里的关键?^准确地说:)低重复率问题。我以为我误解了这个问题,所以我在更新答案时删除了它——但现在又回来了。保留这两个集合有什么问题?每个字典都很小,有着不同的用途,这是一个非常简单的解决方案。我觉得这需要一个中间步骤,在这个步骤中,您可以按值对(键、值)对列表进行排序,否则不能保证相同的值会在迭代中聚集在一起。
from itertools import groupby

x = {
    'bathroom': 'a',
    'bedroom1': 'a',
    'kitchen': 'b'
}


{
  ','.join(i[0] for i in v): k
  for k,v in groupby(sorted(x.iteritems(), key=lambda p: p[1]), lambda p: p[1])
}