我正在做一个文本扭曲程序,我在检查是否可以从给定的一组字母中创建一个单词时遇到了问题。如果没有重复的字母,这很容易,但是如果用户输入一个包含重复字母的单词,我该如何做呢?我使用了元组,但如果字母重复,它就不起作用。
为了让它更清楚,我提供了这个例子:
假设您的字母组是(d,n,a,e,l,i),用户输入单词need。我们可以看到,字母e在这里使用了两次,但由于我编写的代码(使用元组)只是检查列表是否是列表的子集,所以如果不是,它会将need视为正确答案。我该如何修复它?
发布于 2015-05-17 10:41:21
一种方法是使用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'
# or as a three-line function:
def is_contained(a, b):
"""Test if all the letters of word a are contained in word b"""
letters = Counter(b)
letters.subtract(Counter(a))
return all(v >= 0 for v in letters.values())注意:Counter.subtract()不同于-操作,即Counter.__sub__()。Counter.subtract()还将传播负(和零)计数,这是您需要检查的。
@StefanPochmann的方法从候选单词中减去字母;我的方法正好相反。在SP的情况下,正的剩余计数是不好的;在我的情况下,负的是坏的。因此,他的方法不需要关心负数或零计数,但我的方法需要。他的比较简单,因此更好。)
发布于 2015-05-17 10:38:42
是的,集合不起作用,但多集合起作用。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)如果你的两个字母集都很大,而且你的单词很长,这会很慢,但“正常用法”是没问题的。
发布于 2015-05-17 10:50:21
您可以尝试从允许的列表中删除每个字母,直到您完成或出现错误(意味着您无法构建该单词):
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 constructedhttps://stackoverflow.com/questions/30282719
复制相似问题