Python中使用列表的字谜
假设我们有以下字符串列表:Python中使用列表的字谜,python,string,list,anagram,Python,String,List,Anagram,假设我们有以下字符串列表: Input: ["eat", "tea", "tan", "ate", "nat", "bat"] 我们程序的输出应将每一组字谜分组,并将它们作为列表一起返回,如下所示: Output: [ ["ate","eat","tea"], ["nat","tan"], ["bat"] ] 我当前的解决方案找到了第一组字谜,但没有检测到其他两组,而是将第一组复制到列表中: class Solution(object): def groupAnagram
Input: ["eat", "tea", "tan", "ate", "nat", "bat"]
我们程序的输出应将每一组字谜分组,并将它们作为列表一起返回,如下所示:
Output:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
我当前的解决方案找到了第一组字谜,但没有检测到其他两组,而是将第一组复制到列表中:
class Solution(object):
def groupAnagrams(self, strs):
allResults=[]
results=[]
temp=''
for s in strs:
temp=s[1:]+s[:1]
for i in range(0,len(strs)):
if temp==strs[i]:
results.append(strs[i])
allResults.append(results)
return allResults
输出为:
[["ate","eat","tea"],["ate","eat","tea"],["ate","eat","tea"],["ate","eat","tea"],["ate","eat","tea"],["ate","eat","tea"]]
如何解决这个问题
编辑:
通过将结果附加到第二个循环之外的所有结果中,我修复了附加中的重复:
class Solution(object):
def groupAnagrams(self, strs):
allResults=[]
results=[]
temp=''
for s in strs:
temp=s[1:]+s[:1]
for i in range(0,len(strs)):
if temp==strs[i]:
results.append(strs[i])
allResults.append(results)
print(results)
return allResults
但是,它没有检测到其他两组字谜。您可以使用python内置集合库中的defaultdict并排序:
In [1]: l = ["eat", "tea", "tan", "ate", "nat", "bat"]
In [2]: from collections import defaultdict
In [3]: d = defaultdict(list)
In [4]: for x in l:
...: d[str(sorted(x))].append(x)
In [5]: d.values()
Out[5]: dict_values([['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']])
要修复您的问题,您需要添加要检查的变量。例如,Please和我使用enumerate在搜索字谜时性能不佳的Str中的while walk:
class Solution(object):
def groupAnagrams(self, strs):
allResults = []
added = set([])
temp=''
for i, s in enumerate(strs):
results = []
unique_s = "".join(sorted(s))
if unique_s in added:
continue
else:
added.add(unique_s)
for x in strs[i:]:
if unique_s=="".join(sorted(x)):
results.append(strs[i])
allResults.append(results)print(added)
return allResults
在实现函数的方式中,您只需要查看字符串的旋转,即将字母从开头移动到结尾,例如a-t-e->t-e-a->e-a-t。您的算法无法检测的是单个排列,如果您只切换两个字母n-a-t->t-a-n。在数学语言中,你只考虑三个字母串的排列,而不是奇数排列。 例如,对代码的修改可以是:
def get_list_of_permutations(input_string):
list_out = []
if len(input_string) > 1:
first_char = input_string[0]
remaining_string = input_string[1:]
remaining_string_permutations = get_list_of_permutations(remaining_string)
for i in range(len(remaining_string)+1):
for permutation in remaining_string_permutations:
list_out.append(permutation[0:i]+first_char+permutation[i:])
else:
return [input_string]
return list_out
def groupAnagrams(strs):
allResults=[]
for s in strs:
results = []
list_of_permutations = get_list_of_permutations(s)
for i in range(0,len(strs)):
if strs[i] in list_of_permutations:
results.append(strs[i])
if results not in allResults:
allResults.append(results)
return allResults
输出是
Out[218]: [['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']]
编辑:修改代码以处理所有长度的字符串。使用itertools.groupby
仅使用问题标题中要求的列表:
第二行s_单词获取单词中每个单词的所有字母,对它们进行排序,并重新创建一个由该单词的已排序字母组成的字符串;它创建所有这些已排序字母字符串的列表,其顺序与原始单词序列相同->这将用于比较可能的字谜。字谜的字母在排序时产生相同的字符串
第三行索引保存True或False值,以指示是否已提取相应的单词,并避免重复
下面的代码是一个双循环,对于每个s_单词,确定哪些其他s_单词相同,并使用其索引检索原始单词列表中的相应单词;它还更新了指数的真值
words = ["eat", "tea", "tan", "ate", "nat", "bat"]
s_words = [''.join(sorted(list(word))) for word in words]
indices = [False for _ in range(len(words))]
anagrams = []
for idx, s_word in enumerate(s_words):
if indices[idx]:
continue
ana = [words[idx]]
for jdx, word in enumerate(words):
if idx != jdx and not indices[jdx] and s_word == s_words[jdx]:
ana.append(words[jdx])
indices[jdx] = True
anagrams.append(ana)
print(anagrams)
输出:
在重构代码并阻止它生成冗余结果之后,您的代码仍然不能给出预期的结果,因为生成字谜的逻辑并不完全正确
def groupAnagrams(word_list):
allResults=[]
results=[]
for idx,s in enumerate(word_list):
if s == None:
pass
else:
results = [s] # word s is added to anagram list
# you were generating only 1 anagram like for tan --> ant but in word_list only nat was present
for i in range(1,len(s),1):
temp = s[i:]+s[:i] #anagram
# for s = 'tan' it generates only 'ant and 'nta'
# when it should generate all six tna ant nta _nat_ atn tan
if temp in word_list:
results.append(temp)
word_list[word_list.index(temp)] = None
allResults.append(results)
return allResults
print(groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"]))
# [['eat', 'ate', 'tea'], ['tan'], ['nat'], ['bat']]
很好,但是你能修改我自己的代码吗?我想知道我的代码中哪里是错误的,以提高我对python的理解,作为一个新手。如果在某些单词中有重复的字母,使用set来查找字谜将不起作用。你的代码会考虑“帽子”和“那是一个字谜”。you@Ionesome我为你的解决方案扩展了答案,它似乎有一点问题。在我看来,您的代码更改了输入str并将其作为输出返回。我想它们不应该被更改。那么如何修复它呢?你的代码的问题是它只对长度为3的条款有效。你能格式化你的代码吗?缩进不正确,运行代码不容易。现在应该修复。抱歉。提示:当您进入循环的第二次迭代时,结果的值是多少?每次迭代的所有结果的值是多少?打印它们并查看。@molbdnilo你的意思是在if temp…?之前吗?在附加到allResults之后打印它们。@molbdnilo明白了,我知道问题是附加到错误的循环,但是Python没有{}用于块,而是使用缩进,这让我很困惑。我的理解正确吗?@molbdnilo追加中的重复已经修复,但它没有检测到其他两组字谜。如何解决这个问题?你能解释一下你的代码吗?特别是第二行。我添加了一些解释,连同阅读代码将帮助您理解代码是如何工作的。
[['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']]
from itertools import permutations
word_list = ["eat", "tea", "tan", "ate", "nat", "bat"]
anagram_group_list = []
for word in word_list:
if word == None:
pass
else:
anagram_group_list.append([])
for anagram in permutations(word):
anagram = ''.join(anagram)
try:
idx = word_list.index(anagram)
word_list[idx] = None
anagram_group_list[-1].append(anagram)
except ValueError:
pass # this anagram is not present in word_list
print(anagram_group_list)
# [['eat', 'ate', 'tea'], ['tan', 'nat'], ['bat']]
def groupAnagrams(word_list):
allResults=[]
results=[]
for idx,s in enumerate(word_list):
if s == None:
pass
else:
results = [s] # word s is added to anagram list
# you were generating only 1 anagram like for tan --> ant but in word_list only nat was present
for i in range(1,len(s),1):
temp = s[i:]+s[:i] #anagram
# for s = 'tan' it generates only 'ant and 'nta'
# when it should generate all six tna ant nta _nat_ atn tan
if temp in word_list:
results.append(temp)
word_list[word_list.index(temp)] = None
allResults.append(results)
return allResults
print(groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"]))
# [['eat', 'ate', 'tea'], ['tan'], ['nat'], ['bat']]