如何使用Python在单词列表中搜索给定的字母列表

如何使用Python在单词列表中搜索给定的字母列表,python,Python,我有以下信件清单: letters = ['t', 'u', 'v', 'w', 'x', 'y', 'z'] 以及下列字句: words = ['apple', 'whisky', 'yutz', 'xray', 'tux', 'zebra'] 如果字母列表中存在任何单词组合,如何使用Python进行搜索?就像只是看看它一样,我们可以观察到,两个词“yutz”和“tux”是唯一可以为我们的字母列表构建的词 我是Python新手,我曾尝试为循环制作不同的for,但在任何地方都做不到 for

我有以下信件清单:

letters = ['t', 'u', 'v', 'w', 'x', 'y', 'z']
以及下列字句:

words = ['apple', 'whisky', 'yutz', 'xray', 'tux', 'zebra']
如果字母列表中存在任何单词组合,如何使用Python进行搜索?就像只是看看它一样,我们可以观察到,两个词“yutz”和“tux”是唯一可以为我们的字母列表构建的词

我是Python新手,我曾尝试为循环制作不同的for,但在任何地方都做不到

for word in words:
    for i in letters:
        if i in word:
            print(word)
        else:
            print('not in word')

正如你们所理解的,结果是灾难。

你们需要从不同的角度看待你们的问题。
单词列表中属于字母集合子集的任何单词都可以由这些字母组成。换句话说,
字母
需要是单词的超集:

letters = {'t', 'u', 'v', 'w', 'x', 'y', 'z'}  # a set, not a list
for word in words:
    if letters.issuperset(word):
        print(word)
如果iterable参数的所有元素都在集合中,则返回true

如果您想要列表,只需使用列表:

[word for word in words if letters.issuperset(word)]
[word for word in words if not Counter(word) - letters]
演示:

请注意,这只查看唯一的字母
apple
字母集
{'a','p','l','e'}
的子集。如果您也需要处理字母计数,则需要使用multiset;Python有一个名为的实现。这不仅可以记录信件,还可以记录它们的数量

计数器
类型不支持测试子集或超集,因此必须使用减法;如果生成空的
计数器()
,则可以通过字母计数形成整个单词:

letters = Counter(['a', 'p', 'l', 'e', 'p', 'i'])
words = ['apple', 'applepie']
for word in words:
    if not Counter(word) - letters:
        print(word)
或作为列表:

[word for word in words if letters.issuperset(word)]
[word for word in words if not Counter(word) - letters]
这会产生
['apple']
,因为在输入字母多集中只有一个
'e'
,只有2个
'p'
s,而不是3个。

您可以在这里使用:

如果结果为空集,则表示
w
中的每个字符都属于
字母。如果是这种情况,
set.difference
返回一个空的
set
,它是
False
-y,因此
not….
将导致
True
并打印单词。这相当于:

for w in words:
    if not set(w).difference(letters):
        print(w)

yutz
tux

这类似于使用
集进行测试。issuperset
,但从不同的角度解决问题。

您可以使用生成器的
all
函数来确定属于
单词的单词中的所有字符是否都存在于
字母中:

letters = ['t', 'u', 'v', 'w', 'x', 'y', 'z']
words = ['apple', 'whisky', 'yutz', 'xray', 'tux', 'zebra']
final_words = [i for i in words if all(c in letters for c in i)]
输出:

['yutz', 'tux']
您可以使用itertool的排列方法:

一行:

print(set(["".join(permutation) for item in words for permutation in itertools.permutations(letters,len(item)) if "".join(permutation) in words ]))
详细解决方案:

以上列表理解与以下内容相同:

words = ['apple', 'whisky', 'yutz', 'xray', 'tux', 'zebra']

letters = ['t', 'u', 'v', 'w', 'x', 'y', 'z']
import itertools

final=[]
for i in words:
    for k in itertools.permutations(letters,len(i)):
        if "".join(k) in words and "".join(k) not in final:
            final.append("".join(k))

print(final)
输出:

['yutz', 'tux']

将每个单词按字母拆分成单词,然后进行排序和连接,然后将连接的字符串与已排序和连接的字母进行比较。@SergAnuke这里不需要进行排序。每个字母只能使用一次吗?他们不想知道缺少了什么字母,除非单词可以由字母组成。只需要一个简单的子集/超集测试。@MartijnPieters我的答案的精髓正好抓住了这一点。@MartijnPieters我的答案和你的一样有效,我看不出在这里进行向下投票的原因。而创建一个新的集合而不是布尔值是低效的。不需要将每个单词都转换为一个新的set对象,
set.difference()
返回一个完整的set对象,然后只测试它是否包含元素,然后再次丢弃。@MartijnPieters我非常明确地说(在我的初始回答中)“如果结果是一个空集,那意味着w中的每个字符都属于字母。”如果这不能解释我想表达什么,我不知道是什么。假设一个单词有两个字母的实例——但列表中的字母只有一个字母的实例?@SamRedway这回答了是否存在的问题。您上面的陈述适用于使用
集合。计数器
或其他存储字母频率的系统的程序。这是一个问题,而不是一个陈述。我不认为OP在这一点上是明确的。如果这封信可以重复使用,这是有效的。以苹果为例——如果列表中只有一个p,那么它就有两个p——你能从这个列表中生成苹果吗,即['a'、'p'、'l'、'e']?@SamRedway:已经解决了(你发表评论时我正在输入样本)。@MartijnPieters我已经能够解决这个问题,但现在我面临另一个挑战。Scrabble可以有空白块,在python中可以表示为“”。如果在我的示例中,我们使用“”而不是“t”,会怎么样。从人性上来说,我们知道我们可以使用这块空白的瓷砖,制作“ytuz”和“tux”这样的单词。但我们将如何通过编程实现呢?这是非常低效的。你对每个单词都执行O(N!)个不同的测试,其中只需要O(N)个测试。@MartijnPieters我只是向他展示了他可以尝试这个方法,我没有说“你必须”,我知道你的回答很好,我也知道这些方法,所以我应该重复你的答案吗?我只是给出反馈,说明这种方法有多有用,没别的了。