简体   繁体   English

二维字典或其他数据结构,其中键的顺序无关紧要

[英]2D Dictionary or other data structure where order of keys doesn't matter

I want to create a data structure that can take in a pair of keys (strings) and return a value (string as well). 我想创建一个数据结构,可以接受一对键(字符串)并返回一个值(字符串也是如此)。 I would like to return the same value regardless of the order in which the 2 keys are entered (eg data[key1][key2] returns the same value as data[key2][key1]). 无论输入2个键的顺序如何,我都希望返回相同的值(例如,data [key1] [key2]返回与data [key2] [key1]相同的值)。 Is there a term/concept for this description? 这个描述有一个术语/概念吗?

My current implementation is to create a 2D dictionary like this: 我目前的实现是创建一个像这样的2D字典:

my_dict = {'key1': {'key1': None,
                    'key2': 'foo',
                    ...
                    'keyn': 'bar'},
           'key2': {'key1': 'foo',
                    'key2': None,
                    ...
                    'keyn': 'baz'},
           ...
           'keyn': {'key1': 'bar',
                    'key2': 'baz',
                    ...
                    'keyn': None}}

# Calling my_dict['key1']['key2'] and my_dict['key2']['key1'] both return 'foo', which is what I want and expect.

This doesn't seem right to me. 这对我来说似乎不对。 I am duplicating data, and I am creating n * n entries when I only need (n * (n - 1))/2. 我正在复制数据,当我只需要(n *(n - 1))/ 2时,我正在创建n * n个条目。

So, I tried creating a 1D Dictionary where the key is a tuple: 所以,我尝试创建一个字典,其中键是一个元组:

my_dict = {('key1', 'key2'): 'foo'}

But this doesn't work as calling my_dict[('key2', 'key1')] gives me a KeyError 但这不起作用,因为调用my_dict[('key2', 'key1')]给了我一个KeyError

One work-around for the 1D tuple Dictionary is to create a try/except. 1D元组字典的一个解决方法是创建一个try / except。

def get_value(my_dict, key1, key2):
    try:
        return my_dict[key1][key2]
    except KeyError:
        return my_dict[key2][key1]

This doesn't seem intuitive and feels more like a 'band-aid' to the problem. 这似乎不直观,感觉更像是对这个问题的“创可贴”。

One method I haven't tested is a 1D Dictionary where the key uses an instance of a custom-defined class that holds key1 and key2 as attributes. 我没有测试过的一种方法是一维字典,其中密钥使用自定义类的实例,该类将key1key2保存为属性。 In order to do this, the object would have to be nonmutable and hashable, where the hash function would use the object's attributes and produce the same "hash key" regardless of the order of attributes. 为了做到这一点,对象必须是不可变的和可散列的,其中散列函数将使用对象的属性并产生相同的“散列键”而不管属性的顺序如何。 I've never done this before and don't know how to do this. 我以前从未这样做过,也不知道该怎么做。 Is this the right way to go about it? 这是正确的方法吗? I feel very stupid that I haven't been able to figure this out, as it seems like there is an easy answer to this. 我觉得非常愚蠢,我无法弄清楚这一点,因为似乎有一个简单的答案。

If you want the keys to compare equal regardless of order, you could use frozensets as keys which fits in with your idea of a custom class: 如果您希望无论顺序如何都能比较相等的键,您可以使用frozensets作为符合您自定义类的想法的键:

my_dict = {frozenset(['key1', 'key2']): 'foo'}

Does not matter what order you add the keys: 无论您添加密钥的顺序如何:

In [44]: my_dict = {frozenset(['key1', 'key2']): 'foo'}

In [45]: k = frozenset(["key1","key2"])

In [46]: k2 = frozenset(["key2","key1"])

In [47]: my_dict[k]
Out[47]: 'foo'

In [48]: my_dict[k2]
Out[48]: 'foo'

You can have as many values in the frozenset as you want they will still compare equal, using a frozen set is also efficient for lookups: 您可以在冻结集中拥有尽可能多的值,它们仍然可以比较相等,使用冻结集对查找也很有效:

In [55]: timeit my_dict[k]
10000000 loops, best of 3: 103 ns per loop

In [56]: timeit get_value(my_dict, 'key1', 'key2')
1000000 loops, best of 3: 455 ns per loop

In [57]: timeit get_value(my_dict, 'key2', 'key1')
1000000 loops, best of 3: 455 ns per loop

Even timing the frozenet creation and the lookup for two elements is faster: 甚至计时冻结创建和查找两个元素的速度更快:

In [5]: my_dict = {frozenset(['key1', 'key2']): 'foo'}

In [6]: timeit my_dict[frozenset(["key1","key2"])]
1000000 loops, best of 3: 380 ns per loop

For just 3 strings you have 3! 只有3个字符串,你有3个! perms to check, for 6 you have 720 so for anything more than a couple checking every possible permutation is not realistic or remotely efficient. 要检查的权限,对于6你有720所以对于任何超过一对检查每个可能的排列是不现实或远程有效。

You could use an hashable object, as you suggest. 您可以按照建议使用可清除对象。 To achieve this you would need to implement __hash__ , and __eq__ or __cmp__ (one of the two) methods, like so: 要做到这一点,你需要实现__hash____eq____cmp__方法(两个一个),像这样:

class Key:

   def __init__(self, key1, key2):
      self.key1 = key1
      self.key2 = key2

   def __hash__(self):

      # XORing two hash values is usually fine. Besides, the operation is symmetric, which is what you want
      return hash(self.key1) ^ hash(self.key2)

   def __eq__(self, other):

      if self == other:
         return True

      if self.key1 == other.key1 and self.key2 == other.key2:
         return True

      if self.key1 == other.key2 and self.key2 == other.key1:
         return True

      return False

How about 怎么样

my_dict = {('key1', 'key2'): 'foo'}

def get_value(my_dict, key1, key2):
    return my_dict.get((key2, key1) , my_dict.get((key1, key2)))

This way, you have to make less entries, and its better than try/except 这样,你必须减少输入,并且比try/except更好

Example

In [11]: my_dict = {('key1', 'key2'): 'foo'}

In [12]: def get_value(my_dict, key1, key2):
   ....:     return my_dict.get((key2, key1) , my_dict.get((key1, key2)))

In [13]: get_value(my_dict, 'key1', 'key2')
Out[13]: 'foo'

Here's what I found. 这是我发现的。 The dimensions of the lists have to be the same. 列表的尺寸必须相同。

my_dict = {}
sub_dict = {}

ks = ['key1','key2','key3','keyn']
kks = ['key1','key2','key3','keyn']
vals = [None,'foo','bar','baz']

for val in vals:    
    for kk in kks:
        sub_dict[kk] = val

print sub_dict

for k in ks:
    my_dict[k] = sub_dict

print my_dict

Frozenset is probably better. Frozenset可能更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Multiples-keys字典,其中键顺序无关紧要 - Multiples-keys dictionary where key order doesn't matter 使用键作为坐标从字典生成2D数据结构 - Generate a 2D data structure from a dictionary, using keys as coordinates 当与冒号 (:) 一起使用时,为什么 Python 2D 数组索引顺序无关紧要 - Why doesn't the Python 2D array index order matter when used with colon ( : ) 匹配顺序无关紧要的集合中的确切元素 - Matching exact elements in a set where order doesn't matter 2个坐标的快速哈希,顺序无关紧要? - Fast hash for 2 coordinates where order doesn't matter? (pandas)如何根据三个相似的数据列创建唯一标识符,其中顺序无关紧要? - (pandas)How can I create a unique identifier based on three similar columns of data, where order doesn't matter? Python 3.x:如何比较包含字典的两个列表,其中顺序无关紧要 - Python 3.x: How to compare two lists containing dictionaries where order doesn't matter 熊猫:在顺序无关紧要的子集中查找重复项并将其合并 - Pandas: Find duplicates in subset where order doesn't matter and combine them .json 打印数据不遵守 Python 中的字典顺序 - The .json printed data doesn't respect the dictionary order in Python 2D网格的Python数据结构建议 - Python Data Structure Recommendations for a 2D Grid
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM