37

是否可以在 Python 字典中为每个值分配多个键。一种可能的解决方案是为每个键分配值:

dict = {'k1':'v1', 'k2':'v1', 'k3':'v1', 'k4':'v2'}

但这不是内存效率,因为我的数据文件大于 2 GB。否则,您可以制作字典键的字典:

key_dic = {'k1':'k1', 'k2':'k1', 'k3':'k1', 'k4':'k4'}
dict = {'k1':'v1', 'k4':'v2'}
main_key = key_dict['k2']
value = dict[main_key]

这也非常耗费时间和精力,因为我必须浏览整个字典/文件两次。还有其他简单且内置的 Python 解决方案吗?

注意:我的字典值不是简单的字符串(如问题'v1','v2')而是复杂的对象(包含不同的其他字典/列表等,无法腌制它们)

注意:问题似乎类似于如何可以我对同一个字典值同时使用键和索引? 但我不是在寻找有序/索引字典,而是在寻找除此问题中提到的两个之外的其他有效解决方案(如果有的话)。

4

7 回答 7

38

值是什么类型?

dict = {'k1':MyClass(1), 'k2':MyClass(1)}

会给出重复的值对象,但是

v1 = MyClass(1)
dict = {'k1':v1, 'k2':v1}

导致两个键都指向同一个实际对象。

在最初的问题中,您的值是字符串:即使您两次声明相同的字符串,我认为在这种情况下它们将被实习到同一个对象


注意。如果你不确定你是否有重复,你可以像这样找到:

if dict['k1'] is dict['k2']:
    print("good: k1 and k2 refer to the same instance")
else:
    print("bad: k1 and k2 refer to different instances")

is感谢 JFSebastian,替换id()

于 2012-07-12T09:55:28.603 回答
12

看看这个 - 它正是你所要求的实现:multi_key_dict(ionary)

https://pypi.python.org/pypi/multi_key_dict (来源https://github.com/formiaczek/python_data_structures/tree/master/multi_key_dict

(在 Unix 平台上,它可能作为一个包提供,您可以尝试使用以下方式安装它:

sudo apt-get install python-multi-key-dict

对于 Debian,或您的发行版的等价物)

您可以使用不同类型的键,但也可以使用相同类型的键。您还可以使用您选择的键类型迭代项目,例如:

m = multi_key_dict()
m['aa', 12] = 12
m['bb', 1] = 'cc and 1'
m['cc', 13] = 'something else'

print m['aa']   # will print '12'
print m[12]     # will also print '12'

# but also:
for key, value in m.iteritems(int):
    print key, ':', value
# will print:1
# 1 : cc and 1
# 12 : 12
# 13 : something else

# and iterating by string keys:
for key, value in m.iteritems(str):
    print key, ':', value
# will print:
# aa : 12
# cc : something else
# bb : cc and 1

m[12] = 20 # now update the value
print m[12]   # will print '20' (updated value)
print m['aa']   # will also print '20' (it maps to the same element)

键的数量没有限制,所以代码如下:

m['a', 3, 5, 'bb', 33] = 'something' 

是有效的,任何一个键都可以用来引用这样创建的值(读/写或删除它)。

编辑:从 2.0 版开始,它也应该适用于 python3。

于 2013-06-06T16:10:17.947 回答
2

最直接的方法是使用 dict.fromkeys() 方法构建字典。它将一系列键和一个值作为输入,然后将值分配给每个键。
您的代码将是:

dict = dict.fromkeys(['k1', 'k2', 'k3'], 'v1')
dict.update(dict.fromkeys(['k4'], 'v2'))

输出是:

print(dict)
{'k1': 'v1', 'k2': 'v1', 'k3': 'v1', 'k4': 'v2'}
于 2017-12-15T14:12:24.377 回答
2

使用 python 2.7/3,您可以将元组、值对与字典理解结合起来。

keys_values = ( (('k1','k2'), 0), (('k3','k4','k5'), 1) )

d = { key : value for keys, value in keys_values for key in keys }

您也可以类似地更新字典。

keys_values = ( (('k1',), int), (('k3','k4','k6'), int) )

d.update({ key : value for keys, value in keys_values for key in keys })

我认为这并没有真正触及您问题的核心,但鉴于标题,我认为这属于这里。

于 2015-11-26T22:30:13.473 回答
1

您可以构建已从解析数据创建的对象的辅助字典。键是解析的数据,值是你构造的对象——比如字符串值应该被转换为某个特定的对象。这样您就可以控制何时构造新对象:

existing = {}   # auxiliary dictionary for making the duplicates shared
result = {}
for k, v in parsed_data_generator():
    obj = existing.setdefault(v, MyClass(v))  # could be made more efficient
    result[k] = obj

然后所有result字典重复值对象将由MyClass该类的单个对象表示。构建结果后,existing可以删除辅助字典。

这里dict.setdefault()可能是优雅而简短的。但是您应该稍后测试更健谈的解决方案是否效率更高——见下文。原因是它MyClass(v)总是被创建(在上面的例子中)然后如果它的重复存在则被丢弃:

existing = {}   # auxiliary dictionary for making the duplicates shared
result = {}
for k, v in parsed_data_generator():
    if v in existing:
        obj = existing[v]
    else:
        obj = MyClass(v)
        existing[v] = obj

    result[k] = obj

v当没有转换为任何特殊时,也可以使用此技术。例如,如果v是字符串,则辅助字典中的键和值将具有相同的值。但是,字典的存在确保了对象将被共享(Python 并不总是确保这一点)。

于 2012-07-12T14:25:27.610 回答
1

我很惊讶没有人提到将元组与字典一起使用。这工作得很好:

my_dictionary = {}
my_dictionary[('k1', 'k2', 'k3')] = 'v1'
my_dictionary[('k4')] = 'v2'
于 2013-09-06T20:29:18.167 回答
1

我能够使用 pandas MultiIndex实现类似的功能,尽管在我的情况下这些值是标量:

>>> import numpy
>>> import pandas
>>> keys = [numpy.array(['a', 'b', 'c']), numpy.array([1, 2, 3])]
>>> df = pandas.DataFrame(['val1', 'val2', 'val3'], index=keys)
>>> df.index.names = ['str', 'int']
>>> df.xs('b', axis=0, level='str')
        0
int      
2    val2

>>> df.xs(3, axis=0, level='int')
        0
str      
c    val3
于 2015-08-20T11:37:00.227 回答