是否可以在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')而是相当复杂的对象(包含不同的其他字典/列表等,并且不可能腌制它们)
注意:问题与How can I use both a key and an index for the same dictionary value?类似
但我不是在寻找有序/索引的字典,我正在寻找其他有效的解决方案(如果有的话),除了这个问题中提到的两个。
答案 0 :(得分:37)
这些值是什么类型的?
dict = {'k1':MyClass(1), 'k2':MyClass(1)}
将提供重复的值对象,但
v1 = MyClass(1)
dict = {'k1':v1, 'k2':v1}
导致两个键都引用相同的实际对象。
在原始问题中,你的值是字符串:即使你两次声明相同的字符串,我认为在这种情况下它们将被插入同一个对象
NB。如果你不确定你是否最终得到重复,你可以这样找到:
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
感谢J.F.Sebastian,取代id()
)
答案 1 :(得分:10)
看看这个 - 它正是你所要求的实现: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。
答案 2 :(得分:2)
我很惊讶没有人提到过使用带有字典的元组。这很好用:
my_dictionary = {}
my_dictionary[('k1', 'k2', 'k3')] = 'v1'
my_dictionary[('k4')] = 'v2'
答案 3 :(得分: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 })
我不认为这真的是你的问题的核心,但鉴于标题,我认为这属于这里。
答案 4 :(得分:2)
最直接的方法是使用dict.fromkeys()方法构建字典。它将一系列键和一个值作为输入,然后将值分配给每个键 你的代码是:
$scope.toggleDisplay = function() {
var child = document.querySelector( ".question-content" );
var hidden = child.getAttribute("aria-hidden");
var expanded = child.getAttribute("aria-expanded");
hidden === "true" ? hidden = false : hidden = true;
expanded === "true" ? expanded = false : expanded = true;
child.setAttribute("aria-hidden", hidden);
child.setAttribute("aria-expanded", expanded);
};
输出是:
dict = dict.fromkeys(['k1', 'k2', 'k3'], 'v1')
dict.update(dict.fromkeys(['k4'], 'v2'))
答案 5 :(得分: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并不总能确保这一点)。
答案 6 :(得分: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