我有一个字典,其中字母对应于数字和字符串,并且如果每个字母在字符串中出现的次数等于或小于字典中与该字母相关联的数字,则寻求返回True。当这个问题不那么复杂并且没有计算出现次数的限制时,我使用了all(x in string for x in dictionary)
。是否有类似的简洁方法来根据字典中的int值进行测试?
编辑:道歉,这是我们正在关注的内容。
def isValidWord(word, hand, wordList):
"""
Returns True if word is in the wordList and is entirely
composed of letters in the hand. Otherwise, returns False.
Does not mutate hand or wordList.
word: string
hand: dictionary (string -> int)
wordList: list of lowercase strings
"""
if word.lower() in wordList and all(x in hand for x in word):
return True
else:
return False
如果字符串中字母的任何实例显示为Hand的字典键,则此代码返回True,当我现在需要它返回False时,除非该字母出现的次数是< =该键的int值。我已经相当混乱地完成了这项工作,并且想知道是否有办法将这种特殊程度纳入all
方法或类似简洁的方法。
答案 0 :(得分:1)
从您的文档字符串中,您要确定是否可以使用word
中的字母形成hand
。使用collections.Counter
非常简单。你甚至不需要让hand
成为一本字典。
def is_valid_word(word, hand, word_list):
wc, hc = Counter(word), Counter(hand)
return word.lower() in word_list and all(wc[k] <= hc[k] for k in wc)
如果您想将hand
保留为字典,请在最后一行中使用hand
代替hc
,而忽略将其转换为Counter
。
这在复杂性方面并不是最优的,但是可以使用相同的一般概念来编写好的算法。请注意,这比使用count
更有效,因为每个字符串只需要迭代一次而不是每个唯一字母一次。
检查此功能的更有效的功能可能类似于:
def is_partial_anagram(word, pool):
pool_counter = Counter(pool)
for c in word:
if not pool_counter[c]:
return False
pool_counter[c] -= 1
return True
此处的复杂性渐近相同,但在没有匹配时会更快返回False
并避免构建Counter
word
。
答案 1 :(得分:1)
如果我理解正确,你的hand
字典形成如下:
hand = {"f": 1, "o": 2, "b": 1, "a": 1, "r": 1, "z": 0}
并且您希望它与foo
和bar
匹配,但不是baz
,因为z
设置为0
并且至少有一个{{1} }}。您可以使用z
来执行此操作,例如:
str.count()
不是最有效但应该给你的想法。你可以用以下方法测试它:
def isValidWord(word, hand, wordList):
if word.lower() in wordList and all(hand.get(x, 0) >= word.count(x) for x in set(word)):
return True
else:
return False