【问题标题】:Many-to-one mapping (creating equivalence classes)多对一映射(创建等价类)
【发布时间】:2009-12-17 11:08:36
【问题描述】:

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

例如,假设原始类别为:parrot, spam, cheese_shop, Cleese, Gilliam, Palin

现在这对我来说有点冗长,我希望将这些行归类为 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'

任何想法如何在 Python 中创建一个优雅的多对一字典?

【问题讨论】:

  • 查看这个优雅的answer 来回答类似的问题。

标签: python many-to-one equivalence-classes


【解决方案1】:

在我看来,您有两个顾虑。首先,你最初是如何表达你的映射的,也就是说,你如何将映射输入到你的 new_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_monty 来完成这项工作。

【讨论】:

  • +1 非常感谢。我假设这项工作没有 python 本机类型;你认为应该有一个吗?
  • 我们不能有一些引用作为(键,值)对中的值,而不是存储实际的字符串吗?由于没有。的键显着大于编号。值,这将节省大量空间。有没有办法做到这一点?
  • 老问题,但关于 @ishan3243 的观察,我很确定 Python 会实习这些字符串,因为它们被明确定义为常量。此外,即使这些值是在运行时读入的,由于这段代码如何循环并将相同的变量分配给每个索引,它应该会导致字符串停顿。
【解决方案2】:

您可以覆盖 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 循环可以被压缩成一个令人印象深刻的单行,但这有效且可读。)

【讨论】:

  • 不适合胆小的人:equiv_dict = dict( sum([[(k, v) for k in ks] for (ks, v) in assoc_list], []) )
【解决方案3】:

如果你想让多个键指向同一个值,即

m_dictionary{('k1', 'k2', 'k3', 'k4'):1, ('k5', 'k6'):2} 并以以下身份访问它们,

`print(m_dictionary['k1'])` ==> `1`.

检查这个多字典python模块multi_key_dict。安装并导入它。 https://pypi.python.org/pypi/multi_key_dict

【讨论】:

    【解决方案4】:
    >>> 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'
    

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

    【讨论】:

    • 慢,但从好的方面来说,不需要持久的二级数据结构。通过不写成 lambda 并使用列表推导,可以在一定程度上加快速度。
    猜你喜欢
    • 2019-01-12
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 2014-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多