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

Oli*_*Oli 5 python

所以这是一个奇怪的问题,我怀疑这个问题很难解决.我正在为我家中的远程玩家构建一个歌词webapp.它目前生成一个他们正在播放的歌曲的球员字典.例如:

{
    '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)>,
}
Run Code Online (Sandbox Code Playgroud)

偶尔会同步这些玩家的子集.所以 - 在上面 - 它们显示相同的值.我想在界面中对这些进行分组.当我构建字典时,我可能会更聪明,但假设我不会这样做,是否有一种通过值合并键的好方法?

以上所需的输出将是:

{
    'bathroom,bedroom1': <Song: Blur - Song 2>,
    'kitchen': <Song: Meat Loaf - I'd Do Anything for Love (But I Won't Do That)>,
}
Run Code Online (Sandbox Code Playgroud)

然而,这确实打破了我想要查找的东西(我想通过名称指定,因此这是一个字典)...是否有一个更好的集合,每个值可以有多个键并指示何时合并重复(并向后 - 指向他们所有的键)?


有一个很好的答案可以将其翻到歌曲的关键字,并将播放列表作为一个值.这很棒,除了有时候我想知道哪首歌在一个指定的播放器上播放.这就是我最初使用字典的原因.

有没有一种很好的方法来保持两个方向的查找(没有保持两个集合)?

And*_*rey 7

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])
}
Run Code Online (Sandbox Code Playgroud)

  • 在我看来,这需要一个中间步骤,您可以按值对(键,值)对列表进行排序,否则不能保证相同的值会在迭代中聚集在一起. (3认同)

Dav*_*d Z 2

当涉及的数据量很大时,关系数据库就可以派上用场。具有两列(键和值)以及键列上的索引的数据库的行为有点像字典。但您也可以在值列上放置索引以实现高效的反向查找。

不过,就您而言,由于涉及的数据量很小,我只需创建一个defaultdict,然后添加(value, key)对。

reverse_lookup = defaultdict(list)
for k, v in now_playing.items():
    reverse_lookup[v].append(k)
Run Code Online (Sandbox Code Playgroud)

然后您可以','.join()使用这些值来生成复合键。由于这些复合键将用于显示,看起来并不是真正用于查找,我只是将原始字典和反向查找字典都保留在内存中,并在需要执行查找时使用您需要的任何一个。查找与给定歌曲播放同一首歌曲(并且可能已同步)的其他玩家的任务涉及两次查找,一次向前,一次反向,但它们是哈希表查找,因此增加的成本很小。


经过一番思考后,其他更“有趣”的方法可以做到这一点:您也许能够改变不相交的集合数据结构来满足您的需求。您将为每个播放器提供一个节点,并为当前正在播放的每首歌曲提供一个节点。这些节点按歌曲分组为组,其中一组包含歌曲的节点以及当前播放该歌曲的任何玩家的节点。如果将每个集合的节点(歌曲加播放器)放入循环链表中,只要正确维护整体数据结构,您就可以从任何节点开始并遍历列表以迭代歌曲和播放器列表。正在播放那首歌。

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