【问题标题】:How do I make a dictionary with multiple keys to one value?如何制作具有多个键的字典?
【发布时间】:2012-04-24 19:34:18
【问题描述】:

我有一个关于我想要制作的字典的问题。我的目标是为单个值提供多个键,如下所示:

dictionary = {('a', 'b'): 1, ('c', 'd'): 2}
assert dictionary['a'] == 1
assert dictionary['b'] == 1

有什么想法吗?

【问题讨论】:

  • @evil_inside,啊,如果这是你想要的,你为什么不给两个键都分配1?
  • @Eli,这不是重复的。实际上,该链接是此链接的副本。查看帖子的时间。

标签: python dictionary


【解决方案1】:

短期和中间版本

拥有多个键

#!/usr/bin/env python3

def get_keys(s):
    # Lower the user's entry to easily manipulate data
    s = s.lower()
    
    # Create a list to simulate multiple keys
    numbers = ['uno', 'one', 'um', 'eins', 'ein']
    
    # Lambda for input validation
    validator = lambda x: x if x in numbers else 'no-key-found'  # return me x if x is found in the list numbers, contratiwise return me 'no-key-found'
    
    dic = {
        validator(s):'1',
        'no-key-found':'Key does not exist'
    }
    
    
    return dic[validator(s)]


print(get_keys(input('Type in word: ')))

更简单的版本

#!/usr/bin/env python3

import sys


def week_days():
    # Assets
    number_day = ['1', '2', '3', '4', '5', '6', '7']
    
    # Introduction
    print('Welcome to the Week Day Finder')
    
    # User input
    day = input('Please, enter the day you want to check: ').lower()
    WEEK_COLOR = {'RED': '\u001b[31m', 'GREEN': '\u001b[32m'}
    
    # Day validator
    days = {
        '1' if day in number_day else 'sunday': 'Weekend Day',
        '2' if day in number_day else 'monday': 'Week Day',
        '3' if day in number_day else 'tuesday': 'Week Day',
        '4' if day in number_day else 'wednesday': 'Week Day',
        '5' if day in number_day else 'thursday': 'Week Day',
        '6' if day in number_day else 'friday': 'Week Day',
        '7' if day in number_day else 'saturday': 'Weekend Day'
    }
    
    # Logical trial
    try:
        if days[day] == 'Week Day':
            print(WEEK_COLOR['GREEN'], days[day])
            
        elif days[day] == 'Weekend Day':
            print(WEEK_COLOR['RED'], days[day])
            
    except KeyError:
        print('** Invalid Day **', file=sys.stderr)
        
        
def main():
    week_days()
    
    
if __name__ == '__main__':
    main()

【讨论】:

    【解决方案2】:

    如果您要经常添加到这本字典中,您会想要采用基于类的方法,类似于@Latty 在这个 SO 问题 2d-dictionary-with-many-keys-that-will-return-the-same-value 中的回答。

    但是,如果您有一个静态字典,并且您只需要通过多个键访问值,那么您可以采用使用两个字典的非常简单的方法。一个用于存储别名键关联,一个用于存储您的实际数据:

    alias = {
        'a': 'id1',
        'b': 'id1',
        'c': 'id2',
        'd': 'id2'
    }
    
    dictionary = {
        'id1': 1,
        'id2': 2
    }
    
    dictionary[alias['a']]
    

    如果你需要添加到字典中,你可以编写一个这样的函数来使用两个字典:

    def add(key, id, value=None)
        if id in dictionary:
            if key in alias:
                # Do nothing
                pass
            else:
                alias[key] = id
        else:
            dictionary[id] = value
            alias[key] = id
    
    add('e', 'id2')
    add('f', 'id3', 3)
    

    虽然这可行,但我认为最终如果你想做这样的事情,编写你自己的数据结构可能是要走的路,尽管它可以使用类似的结构。

    【讨论】:

      【解决方案3】:

      这很简单。首先你要了解 Python 解释器的设计。如果任何两个或多个变量具有相同的值,它基本上不会为所有变量分配内存,它只是映射到该值。

      我们来看代码示例,

      In [6]: a = 10
      
      In [7]: id(a)
      Out[7]: 10914656
      
      In [8]: b = 10
      
      In [9]: id(b)
      Out[9]: 10914656
      
      In [10]: c = 11
      
      In [11]: id(c)
      Out[11]: 10914688
      
      In [12]: d = 21
      
      In [13]: id(d)
      Out[13]: 10915008
      
      In [14]: e = 11
      
      In [15]: id(e)
      Out[15]: 10914688
      
      In [16]: e = 21
      
      In [17]: id(e)
      Out[17]: 10915008
      
      In [18]: e is d
      Out[18]: True
      In [19]: e = 30
      
      In [20]: id(e)
      Out[20]: 10915296
      

      从上面的输出中,变量 a 和 b 共享相同的内存,当我创建一个新变量 e 并存储变量 c 中已经存在的值 (11) 时,c 和 d 具有不同的内存,因此它映射到那个内存位置,并且当我将变量 e 中存在的值更改为 21 时不会创建新内存,该值已经存在于变量 d 中,因此现在变量 d 和 e 共享相同的内存位置。最后,我将变量 e 中的值更改为 30,该值未存储在任何其他变量中,因此它为 e 创建了一个新内存。

      所以任何具有相同值的变量共享内存。

      不适用于列表和字典对象

      让我们来回答你的问题。

      当多个键具有相同的值时,所有键都共享相同的内存,因此您期望的东西已经存在于 python 中。

      你可以像这样简单地使用它

      In [49]: dictionary = {
          ...:     'k1':1,
          ...:     'k2':1,
          ...:     'k3':2,
          ...:     'k4':2}
          ...:     
          ...:     
      
      In [50]: id(dictionary['k1'])
      Out[50]: 10914368
      
      In [51]: id(dictionary['k2'])
      Out[51]: 10914368
      
      In [52]: id(dictionary['k3'])
      Out[52]: 10914400
      
      In [53]: id(dictionary['k4'])
      Out[53]: 10914400
      

      从上面的输出中,键 k1 和 k2 映射到相同的地址,这意味着值一个在内存中只存储一次,这是多键单值字典,这就是你想要的。 :P

      【讨论】:

      • 我相信这只是因为 Python 存储了较小数量的对象,因此不必每次都重新创建它们。如果您要存储更复杂的数据,例如更大的数字或字符串等,则情况并非如此。
      • 这不是一个答案,也是一个不好的方向。它甚至没有做 OP 想要的事情:dictionary['k2'] = 3 使 'k2' 映射到 3,而 'k1' 仍然映射到 1。这个 ID 内容只是对 Python 如何在引擎盖下工作的好奇。 Python 不是 C,你不能用指针来破解并期望它能够工作。即使在它可以按预期工作的地方(不是这里的情况),也绝对不应该在任何从远处看到生产代码的代码中使用它。
      【解决方案4】:

      我猜你的意思是:

      class Value:
          def __init__(self, v=None):
              self.v = v
      
      v1 = Value(1)
      v2 = Value(2)
      
      d = {'a': v1, 'b': v1, 'c': v2, 'd': v2}
      d['a'].v += 1
      
      d['b'].v == 2 # True
      
      • Python 的字符串和数字是不可变的对象,
      • 因此,如果您希望 d['a']d['b'] 指向 相同的值,在其更改时会“更新”,请将该值引用为 可变对象(如上所述的用户定义类,或dictlistset)。
      • 然后,当您修改d['a'] 处的对象时,d['b'] 同时更改,因为它们都指向同一个对象。

      【讨论】:

      • 您不必使用不可变对象,只需使用相同的变量(对对象的引用)分配值,可变对象和不可变对象都会得到相同的结果,例如num = 2而不是直接的对象(num 是变量,2 是对象)。您可以使用is 关键字对其进行测试,例如:if d['a'] is d['b']: 。如果两个键都指向同一个对象,则表达式将为True
      • @Yomi 这不适用于分配新的(不可变的)对象!它们最初可能指向同一个对象(使用整数,即使您将文字值放在那里)。但是尝试将d['a'] 的值重新分配给不同的整数变量,并看到d['b'] 不会改变。使用变量名还是文字编号都没有关系,因为它只将一个新的(不可变的)对象分配给一个字典条目,而不是另一个。它不知道哪个键与值具有相同的对象,哪个也应该更改为指向另一个对象。
      【解决方案5】:

      如果使用fromkeys,您的示例会创建多个键:值对。如果您不想这样做,您可以使用一个密钥并为该密钥创建一个别名。例如,如果您使用寄存器映射,您的键可以是寄存器地址,别名可以是寄存器名称。这样您就可以对正确的寄存器执行读/写操作。

      >>> mydict = {}
      >>> mydict[(1,2)] = [30, 20]
      >>> alias1 = (1,2)
      >>> print mydict[alias1]
      [30, 20]
      >>> mydict[(1,3)] = [30, 30]
      >>> print mydict
      {(1, 2): [30, 20], (1, 3): [30, 30]}
      >>> alias1 in mydict
      True
      

      【讨论】:

        猜你喜欢
        • 2015-11-16
        • 2021-05-24
        • 1970-01-01
        • 1970-01-01
        • 2019-04-14
        • 2013-05-21
        • 2021-06-14
        • 2017-07-14
        • 1970-01-01
        相关资源
        最近更新 更多