每个值有多个键

时间:2012-07-12 09:49:38

标签: python python-3.x python-2.7

是否可以在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?类似  但我不是在寻找有序/索引的字典,我正在寻找其他有效的解决方案(如果有的话),除了这个问题中提到的两个。

7 个答案:

答案 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