Python 多对一映射(创建等价类)

Python 多对一映射(创建等价类),python,many-to-one,equivalence-classes,Python,Many To One,Equivalence Classes,我有一个将一个数据库转换为另一个数据库的项目。原始数据库列之一定义了行的类别。此列应映射到新数据库中的新类别 例如,假设原始类别为:parrot、spam、cheese\u shop、Cleese、Gilliam、Palin 这对我来说有点冗长,我想把这些行分类为sketch,actor——也就是说,将所有的sketch和actor定义为两个等价类 >>> monty={'parrot':'sketch', 'spam':'sketch', 'cheese_shop':'ske

我有一个将一个数据库转换为另一个数据库的项目。原始数据库列之一定义了行的类别。此列应映射到新数据库中的新类别

例如,假设原始类别为:
parrot、spam、cheese\u shop、Cleese、Gilliam、Palin

这对我来说有点冗长,我想把这些行分类为
sketch,actor
——也就是说,将所有的sketch和actor定义为两个等价类

>>> monty={'parrot':'sketch', 'spam':'sketch', 'cheese_shop':'sketch', 
'Cleese':'actor', 'Gilliam':'actor', 'Palin':'actor'}
>>> monty
{'Gilliam': 'actor', 'Cleese': 'actor', 'parrot': 'sketch', 'spam': 'sketch', 
'Palin': 'actor', 'cheese_shop': 'sketch'}
这太尴尬了-我更喜欢吃这样的东西:

monty={ ('parrot','spam','cheese_shop'): 'sketch', 
        ('Cleese', 'Gilliam', 'Palin') : 'actors'}
当然,这会将整个元组设置为键:

>>> monty['parrot']

Traceback (most recent call last):
  File "<pyshell#29>", line 1, in <module>
    monty['parrot']
KeyError: 'parrot'
蒙蒂[鹦鹉] 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 蒙蒂[鹦鹉] 关键错误:“鹦鹉” 你知道如何用Python创建一个优雅的多对一字典吗

>>> monty={ ('parrot','spam','cheese_shop'): 'sketch', 
        ('Cleese', 'Gilliam', 'Palin') : 'actors'}

>>> item=lambda x:[z for y,z in monty.items() if x in y][0]
>>>
>>> item("parrot")
'sketch'
>>> item("Cleese")
'actors'

但让我告诉你,它会比普通的一对一字典慢。

你可以覆盖dict的索引器,但也许以下更简单的解决方案会更好:

>>> assoc_list = ( (('parrot','spam','cheese_shop'), 'sketch'), (('Cleese', 'Gilliam', 'Palin'), 'actors') )
>>> equiv_dict = dict()
>>> for keys, value in assoc_list:
    for key in keys:
        equiv_dict[key] = value


>>> equiv_dict['parrot']
'sketch'
>>> equiv_dict['spam']
'sketch'

(也许嵌套的for循环可以压缩成令人印象深刻的一行代码,但这是可行的,并且可读。)

在我看来,您有两个问题。首先,您最初是如何表达映射的,也就是说,如何将映射键入新的_mapping.py文件中。第二,在重新映射过程中映射是如何工作的。这两种表述没有理由是相同的

从您喜欢的映射开始:

monty = { 
    ('parrot','spam','cheese_shop'): 'sketch', 
    ('Cleese', 'Gilliam', 'Palin') : 'actors',
}
然后将其转换为所需的映射:

working_monty = {}
for k, v in monty.items():
    for key in k:
        working_monty[key] = v
制作:

{'Gilliam': 'actors', 'Cleese': 'actors', 'parrot': 'sketch', 'spam': 'sketch', 'Palin': 'actors', 'cheese_shop': 'sketch'}

然后使用
working\u monty
执行此操作。

如果希望多个键指向相同的值,即

m_dictionary{('k1','k2','k3','k4'):1,('k5','k6'):2}
并作为

`print(m_dictionary['k1'])` ==> `1`.
检查此多字典python模块
multi\u key\u dict
。安装并导入它。

不适用于心脏虚弱者:等效dict=dict(sum([[(k,v)表示k在ks中]表示(ks,v)在assoc_列表中])+1非常感谢。我假设这个作业没有python本机类型;你认为应该有一个吗?我们不能在(key,value)对中有一些引用作为值,而不是存储实际的字符串吗?由于键的数量明显大于值的数量,这将节省大量空间。有办法做到这一点吗?老问题,但关于@ishan3243的观察,我非常确定Python会对这些字符串进行内部处理,因为它们被显式定义为常量。此外,即使在运行时读入这些值,由于此代码如何循环并将相同的变量分配给每个索引,它也会导致string interning.Slow-ish,但从另一方面来说,它不需要持久的二级数据结构。如果不是以lambda的形式编写,使用列表理解,可以在一定程度上加快速度。请查看这个优雅的问题,并回答类似的问题。