我正在进行文字扭曲程序,并且我在检查是否可以从给定的字母组中创建单词时遇到问题。如果没有重复的字母,这很容易,但如果用户输入一个重复字母的单词,我该怎么做呢?我使用了元组,但如果字母重复则不起作用。
为了更清楚,我提供了这个例子:
假设您的信件组为(d,n,a,e,l,i)
,并且用户输入了字词need
。我们可以看到这里使用了e
字母两次,但由于我所做的代码(使用元组)只检查列表是否是列表的子集,因此它将need
计为正确答案什么时候不是。我如何解决它?
答案 0 :(得分:1)
一种方法,使用collections.Counter:
from collections import Counter
bag = Counter('dnaeli')
>>> Counter({'a': 1, 'e': 1, 'd': 1, 'i': 1, 'l': 1, 'n': 1})
bag.subtract(Counter('need'))
>>> Counter({'a': 1, 'i': 1, 'l': 1, 'd': 0, 'n': 0, 'e': -1})
if all(v >= 0 for v in bag.values()):
print 'Word is contained'
注意:Counter.subtract()
与-
操作不同,即Counter.__sub__()
。 Counter.subtract()
也会传播负(和零)计数,这是您需要检查[*]。
([*] @StefanPochmann的方法从候选词中减去字母;我的情况则相反。在SP的情况下,正剩余计数是坏的;在我的负面是坏的。所以他的方法不需要关心否定或零计数,但我的确如此。他的复杂性较低,因此更好。)
答案 1 :(得分:0)
是的,设置不起作用,但是多重集合可以。 Counter
可用于此目的。
letters = 'dnaeli'
words = 'line', 'linda', 'need', 'den', 'x'
from collections import Counter
for word in words:
if not Counter(word) - Counter(letters):
print(word)
打印:
line
linda
den
可替换地:
for word in words:
if all(letters.count(c) >= word.count(c) for c in word):
print(word)
如果你的信件都非常大并且你的话很长,那么这会很慢,但是#34;正常使用"没关系。
答案 2 :(得分:0)
您可以尝试从允许列表中删除每个字母,直到您完成或出现问题(意味着您无法构造该字词):
def TestInput(user_input_string, avia_letters_list):
for each_letter in user_input_string:
try:
avia_letters_list.remove(each_letter)
except ValueError:
return 'sorry "%s" can not be constructed' % user_input_string
return 'good job, "%s" can be constructed' % user_input_string
usable_letters = ['d', 'n', 'a', 'e', 'l', 'i']
print TestInput('need', usable_letters[:])
print TestInput('lid', usable_letters[:])
print TestInput('nail', usable_letters[:])
输出:
sorry "need" can not be constructed
good job, "lid" can be constructed
good job, "nail" can be constructed