是否可以创建一个python字典,其中包含可以接受各种形式的键?

是否可以创建一个python字典,其中包含可以接受各种形式的键?,python,python-2.7,dictionary,key,Python,Python 2.7,Dictionary,Key,在前面的代码中,我获得了一个由0和1组成的唯一的5项元组(数据元组)。这5项是区分大多数字母(如“B”和“D”)与字典中其他字母的关键。但是,当有两个键具有相同的5个项时,我遇到了一个问题,因此我向元组中添加了10个以上的项(其他标识数据),以帮助进一步区分键;这是我当前词典的摘录: data = (1,1,1,1,1) dict_letters = {(1,1,1,1,1) : 'A', (0,1,1,0,1) : 'B', (

在前面的代码中,我获得了一个由0和1组成的唯一的5项元组(数据元组)。这5项是区分大多数字母(如“B”和“D”)与字典中其他字母的关键。但是,当有两个键具有相同的5个项时,我遇到了一个问题,因此我向元组中添加了10个以上的项(其他标识数据),以帮助进一步区分键;这是我当前词典的摘录:

data = (1,1,1,1,1)

dict_letters = {(1,1,1,1,1) : 'A',
                (0,1,1,0,1) : 'B',
                (1,1,1,1,1) : 'C',   
                (1,0,1,0,1) : 'D'}

def search():
            for key in dict_letters:
                if data == key:
                    print(dict_letters[key])

search()

#when running, this would result in only 'C' being printed; 'A' was never printed
在这篇摘录中,我只为其中一个附加项创建了条件,以区分“A”和“C”。我想知道是否可以忽略其他9个附加项是0还是1,因为它们在区分这两个键时没有用处(我希望忽略的项用
x
标记)。我还想忽略“B”和“D”的10个附加项目,因为前5个项目足以识别。例如,我想让
(0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1)
(0,1,1,0,0,0,0,1,0,1)
,等都读作“B”,而不为“B”编码2047个额外的键

我尝试在字典前设置
x=0或1
,以及
x=0和1
,但这些都不起作用,因为我发现在运行程序后,由于某种原因,键被设置为
(0,1,1,0,1,1,1,1,1,1,1,1,1)

注意:我希望将来至少使用一次所有附加项,因此删除10个附加项中的任何一个都不是一个选项


我对Python也比较陌生,所以如果您能尽可能简单地给出答案,我将不胜感激。提前谢谢你

我的理解是,给定一些
元组
作为键,如果它们与现有键不完全匹配,则希望忽略此
元组
中的某些项

您可以在
collections.UserDict
和自定义
\uuuu getitem\uuuu
方法的帮助下实现自己的类似字典的类

以下实现假定
元组中的条目是
1
0
。如果没有这个假设,它将不得不遍历所有关键点

data = (0,1,1,0,1,1,1,1,1,1,1,1,1,1,1)
data = (0,1,1,0,1,0,0,0,0,0,0,0,0,0,0)
data = (0,1,1,0,1,0,0,1,1,1,0,0,1,0,1)

#x = 0 or 1
dict_letters = {(1,1,1,1,1,x,x,1,x,x,x,x,x,x,x) : 'A',
                (0,1,1,0,1,x,x,x,x,x,x,x,x,x,x) : 'B',
                (1,1,1,1,1,x,x,0,x,x,x,x,x,x,x) : 'C',    
                (1,1,0,0,1,x,x,x,x,x,x,x,x,x,x) : 'D'}

def search():
            for key in dict_letters:
                if data == key:
                    print(dict_letters[key])

search()

#I need to find a way for all of the data tuples to print 'B' after running the program
请注意,
dict
项查找通常为O(1),尽管这使其成为O(2k),其中k是通配符的数目。特别是,这意味着如果通配符的数量不断增加,您最好使用查找为O(n)的
列表。

我们可以使用普通的
dict
来完成此任务,我们只需要为每个字母构建所有可能的键。关键元组包含15个项,每个项有2个不同的值,因此最多只有2**15=32768个不同的模式,这在现代机器上非常小

我们可以使用来高效地生成所有模式<代码>产品
有效地从传递它的参数为
循环创建嵌套的
。下面是该技术的简短说明。下面的代码生成与
10XX01
对应的所有模式

from UserDict import UserDict
# for Python 3 use this import instead:
# from collections import UserDict

from itertools import product

class WildcardDict(UserDict):
    def __getitem__(self, args):
        item, *wildcards = args

        try:
            return self.data[item]
        except KeyError:
            for xs in product((0, 1), repeat=len(wildcards)):
                xs = iter(xs)
                item = tuple(next(xs) if i in wildcards else x for i, x in enumerate(item))
                if item in self.data:
                    return self.data[item]
        raise KeyError(args)

d = WildcardDict()

d[0, 1, 1, 0, 1] = 'B'

print(d[(0, 1, 1, 0, 1), ]) # 'B'
print(d[(0, 1, 0, 0, 0), 2, 4]) # 'B'
输出

from itertools import product

for t in product(*[(1,), (0,), (0, 1), (0, 1), (0,), (1,)]):
    print(t)
from __future__ import print_function
from itertools import product

#x = 0 or 1
X = 'x'
letter_patterns = {
    (1, 1, 1, 1, 1, X, X, 1, X, X, X, X, X, X, X): 'A',
    (0, 1, 1, 0, 1, X, X, X, X, X, X, X, X, X, X): 'B',
    (1, 1, 1, 1, 1, X, X, 0, X, X, X, X, X, X, X): 'C',
    (1, 1, 0, 0, 1, X, X, X, X, X, X, X, X, X, X): 'D',
}

def make_dict(letter_patterns):
    ''' Build a dict of all the bit patterns for each letter '''
    xlate = {0: (0,), 1: (1,), X: (0, 1)}
    letter_dict = {}
    # Generate all of the (0, 1) combinations for each X in each pattern
    for pattern, letter in letter_patterns.items():
        for key in product(*[xlate[u] for u in pattern]):
            letter_dict[key] = letter
    return letter_dict

# test

letter_dict = make_dict(letter_patterns)

test_items = [
    ((1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0), 'A'),
    ((1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1), 'A'),
    ((1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0), 'A'),
    ((0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 'B'),
    ((0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 'B'),
    ((0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1), 'B'),
    ((1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 'C'),
    ((1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1), 'C'),
    ((1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0), 'C'),
    ((1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 'D'),
    ((1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1), 'D'),
    ((1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 'D'),
    ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 'Z'),
]

# Check that each test key gets the correct letter, or returns
# None if the key isn't in letter_dict
for key, true_letter in test_items:
    letter = letter_dict.get(key)
    print(key, true_letter, letter, letter == true_letter)
下面是一些代码,它使用问题中给出的数据构建一个
dict
,您可以使用它进行搜索。我们使用
dict.get
方法,因此如果您查找dict中没有的模式,代码将返回
None

(1, 0, 0, 0, 0, 1)
(1, 0, 0, 1, 0, 1)
(1, 0, 1, 0, 0, 1)
(1, 0, 1, 1, 0, 1)
输出

from itertools import product

for t in product(*[(1,), (0,), (0, 1), (0, 1), (0,), (1,)]):
    print(t)
from __future__ import print_function
from itertools import product

#x = 0 or 1
X = 'x'
letter_patterns = {
    (1, 1, 1, 1, 1, X, X, 1, X, X, X, X, X, X, X): 'A',
    (0, 1, 1, 0, 1, X, X, X, X, X, X, X, X, X, X): 'B',
    (1, 1, 1, 1, 1, X, X, 0, X, X, X, X, X, X, X): 'C',
    (1, 1, 0, 0, 1, X, X, X, X, X, X, X, X, X, X): 'D',
}

def make_dict(letter_patterns):
    ''' Build a dict of all the bit patterns for each letter '''
    xlate = {0: (0,), 1: (1,), X: (0, 1)}
    letter_dict = {}
    # Generate all of the (0, 1) combinations for each X in each pattern
    for pattern, letter in letter_patterns.items():
        for key in product(*[xlate[u] for u in pattern]):
            letter_dict[key] = letter
    return letter_dict

# test

letter_dict = make_dict(letter_patterns)

test_items = [
    ((1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0), 'A'),
    ((1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1), 'A'),
    ((1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0), 'A'),
    ((0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 'B'),
    ((0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 'B'),
    ((0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1), 'B'),
    ((1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 'C'),
    ((1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1), 'C'),
    ((1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0), 'C'),
    ((1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 'D'),
    ((1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1), 'D'),
    ((1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 'D'),
    ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 'Z'),
]

# Check that each test key gets the correct letter, or returns
# None if the key isn't in letter_dict
for key, true_letter in test_items:
    letter = letter_dict.get(key)
    print(key, true_letter, letter, letter == true_letter)
这段代码在Python2和Python3上都能正确运行(在2.6.6和3.6.0上测试)。通过更改

(1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0) A A True
(1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) A A True
(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0) A A True
(0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) B B True
(0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) B B True
(0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1) B B True
(1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) C C True
(1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1) C C True
(1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0) C C True
(1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) D D True
(1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1) D D True
(1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) D D True
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) Z None False


letter\u patterns
中的元组不是很方便,特别是如果您想在
letter\u patterns
中放入大量符号。为了减少键入,而不是使用那些元组,我们可以使用字符串。这是上面代码的一个变体,可以实现这一点。生成的
字母dict
仍然使用元组键,因为我假设这是您从Leap Motion设备硬件获得的

for pattern, letter in letter_patterns.iteritems():

我可以创建一个允许多个不同键输出单个值的字典条目吗?请看“例如,我想要一个方法…”这听起来像是一个。请给我们更多的上下文,这样我们可以建议一个比使用疯狂元组键的dict更好的解决方案。看起来元组键只是整数的二进制表示。为什么不使用它呢?您的编辑告诉我们有关您的解决方案Y的更多信息,但我们需要知道X问题,以便我们可以提供Y的替代方案。听起来您好像在字典键中寻找某种通配符。是吗?我会使用“key”而不是“item”,以符合
dict.items
产生(key,value)对的事实。@PM2Ring我一直使用item和PyCharm自动用“item”完成签名。所以我不想离这个太远,因为有些人可能已经习惯了这个命名法。@OlivierMelançon我真的很喜欢你的方法,但我仍然不确定它是否解决了我所有的问题。(不幸的是,由于某些原因,我无法安装“collections”,因此我将在这里暂时询问潜在的问题)。假设我的
数据
元组是
(0,1,0,1,0)
,字典条目读作
(0,1,x,0,x):'B'
。我的理解是,该函数将尝试不起作用的
(0,1,0,1,0)
,然后尝试
(0,1,0,1)
。如果这种情况继续下去,很快它将达到
(0,1)
,这确实有效,并且它将错误地打印“B”。@但您不必安装集合,它是一个标准库。至于第二和第四个索引,它们有什么特别之处?总是那些被忽视的人吗?@OlivierMelançon谢谢你的帮助,但我认为PM 2Ring的方法有效地解决了我的问题。不过,我非常感谢你通过你的方法来指导我!出于某种原因,当我