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
以前在我的代码中,我获得了一个由0和1(data
元组组成)的唯一5项元组。这5个项目对于区分大多数字母(如“B”和“D”)与我的字典中的其余字母至关重要。但是,当有两个键具有相同的5个项目时,我遇到了一个问题,因此我向元组添加了10个项目(其他识别数据)以帮助进一步区分键;这是我当前词典的摘录:
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
在这段摘录中,我只为其中一个附加项创建了条件,以区分“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,1,1,0,1,1,1,1,1,1,1,1,1,1,1)
,(0,1,1,0,1,0,0,1,1,1,0,0,1,0,1)
等方式全部读作“B”,而无需为“B”编码2047个额外的键。
我尝试在字典之前设置x = 0 or 1
和x = 0 and 1
,但这些不起作用,因为我发现在运行程序后,键因某种原因设置为(0,1,1,0,1,1,1,1,1,1,1,1,1,1,1)
。
注意:我正在考虑将来至少使用所有其他项目,因此不能删除任何10个附加项目。
我对Python也比较陌生,所以如果你能让答案尽可能简单,我将不胜感激。提前谢谢!
答案 0 :(得分:3)
我的理解是,如果某些tuple
为关键字,您希望忽略此tuple
中的某些条目(如果它们与现有密钥不完全匹配)。
您可以在collections.UserDict
和自定义__getitem__
方法的帮助下实施类似字典的课程。
以下实现假定tuple
中的条目为1
或0
。没有这个假设,就必须遍历所有密钥。
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'
请注意,dict
项目查找通常是 O(1),尽管这使得它 O(2 k )其中 k 是通配符的数量。特别是,这意味着如果通配符的数量一直在增长,那么最好使用list
,其中查找将是 O(n)。
答案 1 :(得分:3)
我们可以使用普通dict
来执行此任务,我们只需为每个字母构建所有可能的键。你的关键元组包含15个项目,每个项目有2个不同的值,因此最多只有2 ** 15 = 32768个不同的模式,这在现代机器上非常小。
我们可以使用itertools.product
有效地生成所有模式。 product
从您传递的args中有效地创建嵌套的for
循环。这是该技术的简短说明。以下代码生成与10XX01
对应的所有模式。
from itertools import product
for t in product(*[(1,), (0,), (0, 1), (0, 1), (0,), (1,)]):
print(t)
<强>输出强>
(1, 0, 0, 0, 0, 1)
(1, 0, 0, 1, 0, 1)
(1, 0, 1, 0, 0, 1)
(1, 0, 1, 1, 0, 1)
以下是一些代码,它们使用问题中提供的数据来构建可用于搜索的dict
。我们使用dict.get
方法,这样如果您查找不在dict中的模式,代码将返回None
。
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)
<强>输出强>
(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
此代码在Python 2和3上都正确运行(在2.6.6和3.6.0上测试)。您可以通过更改
使Python 2上的效率略高一些for pattern, letter in letter_patterns.items():
到
for pattern, letter in letter_patterns.iteritems():
<小时/>
letter_patterns
中的元组不是很方便,特别是如果你想在letter_patterns
中加入很多符号。为了减少键入,而不是使用那些元组,我们可以使用字符串。以上是上述代码的变体。结果letter_dict
仍然使用元组键,因为我认为这是您从Leap Motion设备硬件获得的。
letter_patterns = {
'A': '11111xx1xxxxxxx',
'B': '01101xxxxxxxxxx',
'C': '11111xx0xxxxxxx',
'D': '11001xxxxxxxxxx',
}
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 letter, pattern in letter_patterns.items():
for key in product(*[xlate[u] for u in pattern]):
letter_dict[key] = letter
return letter_dict