简体   繁体   English

我需要一个带有两个键的类似字典的结构,您可以在其中获取所有对象的列表,其中一个具有特定值

[英]I need a dict-like structure with two keys, where you can get the list of all objects with a certain value of one of them

Let's say I have a dict that looks like this:假设我有一个看起来像这样的字典:

d['a']['1'] = 'foo'
d['a']['2'] = 'bar'
d['b']['1'] = 'baz'
d['b']['2'] = 'boo'

If I want to get every item where the first key is 'a', I can just do d['a'] and I will get all of them.如果我想得到第一个键是'a'的每一个项目,我可以做d['a']我会得到所有的。 However, what if I want to get all items where the second key is '1'?但是,如果我想获取第二个键为“1”的所有项目怎么办? The only way I can think of is to make a second dictionary with a reverse order of the keys, which requires duplicating the contents.我能想到的唯一方法是制作第二个字典,键的顺序相反,这需要复制内容。 Is there a way to do this within a single structure?有没有办法在一个单一的结构中做到这一点?

Edit: forgot to mention: I want to do this without iterating over everything.编辑:忘了提:我想在不迭代所有内容的情况下做到这一点。 I'm going to be dealing with dicts with hundreds of thousands of keys, so I need something scalable.我将要处理具有数十万个键的字典,所以我需要一些可扩展的东西。

You're dealing with three dictionaries in this example: One with the values "foo" and "bar", one with the values "baz" and "boo", and an outer dictionary that maps the keys "a" and "b" to those first two inner dictionaries.在此示例中,您正在处理三个字典:一个具有值“foo”和“bar”,一个具有值“baz”和“boo”,以及一个映射键“a”和“b”的外部字典到前两个内部词典。 You can iterate over the keys of both the outer and inner dictionaries with a nested for loop:您可以使用嵌套的 for 循环遍历外部和内部字典的键:

items = []
for outer_key in d:
    for inner_key in d[outer_key]:
        if inner_key == "1":
            items.append(d[outer_key][inner_key])
            break  # No need to keep checking keys once you've found a match

If you don't care about the keys of the outer dictionary, you can also use d.values() to ignore the keys and just see the inner dictionaries, then do a direct membership check on those:如果您不关心外部字典的键,您也可以使用d.values()忽略键并只查看内部字典,然后对这些进行直接成员资格检查:

items = []
for inner_dict in d.values():
    if "1" in inner_dict:
        items.append(inner_dict["1"])

This can also be written as a list comprehension:这也可以写成列表推导:

items = [inner_dict["1"] for inner_dict in d.values() if "1" in inner_dict]

What you want sounds very similar to a tree-structure which can be implemented as a dictionary-of-dictionaries.你想要的听起来非常类似于可以作为字典字典实现的树结构。 Here's a simple implement taken from one of the answers to the question What is the best way to implement nested dictionaries?这是一个简单的实现,取自问题的答案之一实现嵌套字典的最佳方法是什么? :

class Tree(dict):
    def __missing__(self, key):
        value = self[key] = type(self)()
        return value

    def get_second_level(self, second_key):
        found = []
        for level2 in self.values():
            if second_key in level2:
                found.append(level2[second_key])
        return found

d = Tree()
d['a']['1'] = 'foo'
d['a']['2'] = 'bar'
d['b']['1'] = 'baz'
d['b']['2'] = 'boo'
d['c']['2'] = 'mox'
d['c']['3'] = 'nix'

print(d)            # -> {'a': {'1': 'foo', '2': 'bar'}, 'b': {'1': 'baz', '2': 'boo'},
                    #     'c': {'2': 'mox', '3': 'nix'}}
print(d['a'])       # -> {'1': 'foo', '2': 'bar'}
print(d['a']['1'])  # -> foo
print(d['a']['2'])  # -> bar

print()
second_key = '1'
found = d.get_second_level(second_key)
print(f'Those with a second key of {second_key!r}')  # -> Those with a second key of '1'
print(f'  {found}')                                  # ->   ['foo', 'baz']

So after sleeping on it the solution I came up with was to make three dicts, the main one where the data is actually stored and identified by a tuple ( d['a', '1'] = 'foo' ) and the other two are indexes that store all possible values of key B under key A where (A,B) is a valid combination (so a['a'] = ['1', '2'] , b['1'] = ['a', 'b'] . I don't entirely like this, since it still requires a hefty storage overhead and doesn't scale efficiently to higher numbers of keys, but it gets the job done without iterating and without duplicating the data. If anyone has a better idea, I'll be happy to hear it.因此,在睡了之后,我想出的解决方案是制作三个字典,其中数据实际存储并由元组( d['a', '1'] = 'foo' )标识的主要字典和另一个两个是在键 A 下存储键 B 的所有可能值的索引,其中 (A,B) 是有效组合(因此a['a'] = ['1', '2'] , b['1'] = ['a', 'b'] . 我不完全喜欢这个,因为它仍然需要大量的存储开销并且不能有效地扩展到更多的键,但是它可以在不迭代和不复制的情况下完成工作数据。如果有人有更好的主意,我会很高兴听到。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM