试图想出python anagram函数

Posted

技术标签:

【中文标题】试图想出python anagram函数【英文标题】:Trying to come up with python anagram function 【发布时间】:2016-01-06 12:59:46 【问题描述】:

我想要做的是,如果我有一个类似的列表:

["lime", "mile", "liem", "tag", "gat", "goat", "math"]

我想编写一个函数来返回列表中具有字谜的单词,如下所示:

["lime", "mile", "liem", "tag", "gat",]

到目前为止,我有这个代码:

def anagramprinter(x):

    output = []     
    for i in x:
        for n in i:
            if n in x[i]:

我无法通过这部分,希望得到一些帮助,也希望得到详尽的解释。

谁能告诉我一种不涉及导入的方法? 谢谢

谢谢。

【问题讨论】:

【参考方案1】:

一种通过字符的frozenset 识别单词的方法:

from collections import defaultdict

wordlist = ["lime", "mile", "liem", "tag", "gat", "goat", "math"]

worddict = defaultdict(list) 
for word in wordlist:
    worddict[frozenset(word)].append(word)

anagrams = [words for words in worddict.values() if len(words) > 1]
print(anagrams)

# [['lime', 'mile', 'liem'], ['tag', 'gat']]

输出还不是你想要的,但如果你愿意的话,扁平化这个列表很容易。


更新在 cmets 之后:

上面的解决方案不能很好地处理带有重复字符的单词。但这会(这次字典的键只是由排序字母组成的字符串):

for word in wordlist:
    worddict[''.join(sorted(word))].append(word)

【讨论】:

这是否适用于字符串中的重复字符(例如“peace”和“pace”)?【参考方案2】:

分析字谜单词的简单方法是将它们按字母顺序排列。因此,您可以创建第二个按字母顺序排列的单词列表。

['lime', 'mile', 'liem', 'tag', 'gat']

index = 0
b = []
for i in a:
    b.insert(index, ''.join(sorted(i)))
    index = index + 1

['eilm', 'eilm', 'eilm', 'agt', 'agt']

我认为你可以有比我给你的更多的pythonesque代码,但我认为对你来说重要的是对单词中的字母进行排序。

现在你可以做一些事情来分析你的字谜

【讨论】:

很好的接触,避免以后搜索。对于很长的单词也更快。【参考方案3】:

这是一个不错的开始(尽管如果您将变量命名为“wordlist”、“word”(甚至是“w”)和“char”或“c”......)。但是有几个问题:

1:对于每个单词('i'),你需要比较other个单词,希望至少找到一个是i的变位词。

2:您需要查看是否找不到 any 字符。

你可以这样开始:

output = []     
for w1 in wordlist:
    for w2 in wordList:
        if w1==w2: continue  # don't compare to self
        match = True  # hope for the best
        for c in w1:
            if c not in w2: 
                match = False
                break
        if (match):
           output.append(w1)
           break

这很接近,但实际上还不够,因为要成为真正的字谜,每个字母的出现次数必须相同,而不仅仅是相同的一组不同字母(考虑“邮件”与“米拉”或'mailmailmail')。

一种方法是制作 w2 的副本,然后在遍历 w1 的字符时,删除该副本中与 w1 的每个字母匹配的字母。这样它就不能匹配两次。而且,当您完成“c”循环时,您需要确保副本已变为空。

还有很多其他的方法;一些聪明的方法涉及“集合”类型,例如集合和多集合。正如怀斯船长建议的那样,按字母顺序对每个单词中的字符进行排序让您只需比较它们,而不是一次一个地遍历字符。

希望对您有所帮助。

-s

【讨论】:

【参考方案4】:

您可以使用 itertools 创建单词的所有排列,删除您刚刚找到排列的单词,然后一次检查一个单词,看看它是否在这样的排列中

from itertools import permutations

l = ["lime", "mile", "liem", "tag", "gat", "goat", "math"]
final = []
perms = []
for i in l:
    perms += [''.join(p) for p in permutations(i)]
    perms.remove(i)

for i in l:
    if i in perms:
        final.append(i)
print final

这不是世界上最快的解决方案,尤其是当您使用像 'resistance', 'ancestries' 这样的长词时

【讨论】:

【参考方案5】:

在python中检查两个单词是否是字谜的算法。

1) 取两个词:例如

("mile", "lime") ("tiles", "miles")

2) 制作字符串数组/列表:

(['m', 'i', 'l', 'e'], ['l', 'i', 'm', 'e']) (['t', 'i', 'l','e', 's'], ['m', 'i', 'l', 'e', 's'])

3) 对数组排序

(['e', 'i', 'l', 'm'], ['e', 'i', 'l', 'm']) (['e', 'i', 'l','s', 't'], ['e', 'i', 'l', 'm', 's'])

4) 检查first_array[i] == second_array[i] 是否为0<=i<=len(first_array)||second_array

5) 结论。如果 4) 被持有,则返回 true,否则返回 false。

from itertools import combinations

def anagram(w1,w2):
    list1 = list(w1)
    list2 = list(w2)

    list1.sort()
    list2.sort()

    idx = 0
    is_anagram = True

    while idx < len(w1) and is_anagram:
        if list1[idx]== list2[idx]:
            idx += 1
        else:
            is_anagram = False
    return is_anagram


lst_words = ["lime", "mile", "liem", "tag", "gat", "goat", "math"]
lst_anagrams = set()
for i in combinations(lst_words, 2):
    if anagram(*i):
        lst_anagrams |= set(i) 

print list(lst_anagrams)

【讨论】:

【参考方案6】:

检查两个给定的字符串是否是字谜。这些字符串可能包含空格、数字或特殊字符

#First of all define a function that counts the number of alphabets in a string. It'll be used as a final condition to check for anagrams
def count_alpha(text):
    text = text.lower()
    count = 0
    i = 97    #ASCII code range from 'a' to 'z' is 97 to 122
    while i < 123:
        if chr(i) in text:
            count += text.count(chr(i))
        i += 1
    return count
text1 = input('Enter your First Word: ')
text2 = input('Enter your Second Word: ')
#replace all the spaces with empty strings and make the string lower case 
text1 = text1.replace(' ','').lower()
text2 = text2.replace(' ','').lower()
i = 97
while i < 123:
    #check if an alphabet count in both strings is the same.
    if text1.count(chr(i)) == text2.count(chr(i)):
        #replace all the alphabets with spaces
        text1 = text1.replace(chr(i),' ')
        text2 = text2.replace(chr(i),' ')
    i += 1  
#since all the alphabets have been replaced by spaces. There's no alphabet left(if they had the same number of particular alphabets)
if count_alpha(text1) == 0 and count_alpha(text2) == 0:
    print('They are anagrams')
else: print('They are not anagrams')

这是您的代码。享受吧!

【讨论】:

【参考方案7】:
def does_string_contain(big_word, small_word) :
    list_string = list(big_word)
    for char in small_word:
        if char in list_string:
            list_string.pop(list_string.index(char))
        else:
            return False
    for char in small_word:
        if char in list_string:
            return False
    return True

【讨论】:

以上是关于试图想出python anagram函数的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript Anagram 函数的时间复杂度

提高 anagram string 函数的时间效率

我的 Ruby Anagram 无法正常工作

C stdlib函数的Java等价物

MVC 4 Razor - 动态命名javascript函数

如何在Python中实现EXCEL的查找功能