相互检查字符串(Anagrams)

Posted

技术标签:

【中文标题】相互检查字符串(Anagrams)【英文标题】:Checking strings against each other (Anagrams) 【发布时间】:2013-02-06 02:18:25 【问题描述】:

任务是编写一个程序,从用户那里接受两组单词,然后如果这两个单词是字谜(或者至少如果一个单词的所有字母都出现在另一个单词中)和一个如果不是,则为“错误”声明。

作为一个整体编程非常新,我不知道如何超越仅仅索引一个字符串和比较一个字符串的所有部分。我强调我是初学者;我已经阅读了许多用 Python 和 Anagram 标记的其他帖子,它们都在我的脑海中,并参考了我没有被教过的东西。所以越简单越好。到目前为止,这是我的非工作代码:

s1 = input("Please enter a word:")
s2 = input("Please enter another word:")

for i in range(0, len(s1), 1):
    if i in range (0, len(s2), 1):
        print("The letters in your first word are present in your second word.")

【问题讨论】:

主要是关于算法,而不是特定的语言。如果您没有任何开始,我不确定我们是否会在此处为此类问题提供完整的解决方案。 if sorted(s1.lower()) == sorted(s2.lower()): print("Anagram!") 怎么样? :) 【参考方案1】:

为什么不对字符串进行排序?

>>> sorted('anagram')
['a', 'a', 'a', 'g', 'm', 'n', 'r']
>>> sorted('nagaram')
['a', 'a', 'a', 'g', 'm', 'n', 'r']
>>> sorted('anagram') == sorted('nagaram')
True

【讨论】:

【参考方案2】:

您可以使用 collections 库中的魔法 Counter。 来自文档:

这是一个无序集合,其中元素存储为字典键,其计数存储为字典值

因此,您可以使用字符串(可迭代)初始化 Counter 对象,并与字符串中的另一个 Counter 进行比较

from collections import Counter

def is_anagram(str1, str2):
   return Counter(str1) == Counter(str2)

【讨论】:

我比使用sorted 更喜欢这个解决方案,因为它更清楚这里实际做了什么【参考方案3】:

您需要多考虑一下条件逻辑。循环在正确的轨道上,但如果 s1 中有一个字母不在 s2 中,则应将break 退出此循环并打印“False”语句。考虑使用 all_s1_in_s2 = True 之类的变量,然后在发现不匹配的字母时将其设置为 false。

其他一些提示:

for l in s1 将遍历字符串 s1,让您可以按顺序访问每个字母 l - 您根本不需要 rangelen

if .. in 语句可以帮助测试字符串中是否存在字母,例如if letter in mystring: 是一个有效的声明,这可以帮助你很多,同样不需要rangelen

您应该尽可能避免在变量名中使用数字 - 最好是 word_oneword_two,例如

【讨论】:

【参考方案4】:

使用字典检查两个字符串是否是彼此的字谜: 注意:偶数,特殊字符可以作为输入

def anagram(s):
    string_list = []
    for ch in s.lower():
        string_list.append(ch)

    string_dict = 
    for ch in string_list:
        if ch not in string_dict:
            string_dict[ch] = 1
        else:
            string_dict[ch] = string_dict[ch] + 1

    return string_dict



s1 = "master"
s2 = "stream"

a = anagram(s1)
b = anagram(s2)

if a == b:
    print "Anagram"
else:
    print "Not Anagram"

【讨论】:

【参考方案5】:
def is_anagram(w1, w2):
    w1, w2 = list(w1.upper()), list(w2.upper())
    w2.sort()
    w1.sort()
    return w1 == w2

【讨论】:

简洁明了。但为什么不以return w1 == w2 结束呢?【参考方案6】:
>>> s1 = 'vivid'
>>> s2 = 'dvivi'
>>> s3 = 'vivid'
>>> def is_anagram(s1, s2):
...     if s1.lower() == s2.lower():
...         return False
...     return sorted(s1.lower()) == sorted(s2.lower())
...
>>> is_anagram(s1, s2)
True
>>> is_anagram(s1, s3)
False
>>> s2 = 'dvivii'
>>> is_anagram(s1, s2)
False
>>> s2 = 'evivi'
>>> is_anagram(s1, s2)
False
>>> 

【讨论】:

对于isAnagram 函数,您可以只返回计算后的表达式,即return sorted(s..) == sorted(s2)【参考方案7】:

您可以使用以下代码,它不会计算特殊字符,也不会计算数字,如果两个字符串中的总字符相同,则返回“它们是字谜”,因此会告诉字符串是否是字谜。

text = input('Enter a string: ')
text1 = input('Enter a string: ')
text,text1 = text.lower(),text1.lower()
count = 0
count1=0
for i in range(97,123):
    if chr(i) in text and chr(i) in text1:
    count1+=1
        if text.count(chr(i)) == text1.count(chr(i)):
             count +=1
if len(text) >= len(text1):
    num1 = len(text)
else:
    num1 = len(text1)
if count == count1:
    print("they are anagrams")
else :
    print("they are not anagrams")

【讨论】:

【参考方案8】:

如果你坚持使用 Python 字典并且不能使用函数式编程,这里有一个解决方案:

使用理解创建字典,并使用简单的== 运算符比较两个单词的字典。

def isanagram2(wrd1, wrd2):

    wrd1_dict = k: 0 for k in wrd1
    wrd2_dict = k: 0 for k in wrd2

    for c1, c2 in zip(wrd1, wrd2):
        wrd1_dict[c1] += 1
        wrd2_dict[c2] += 1

    if wrd1_dict == wrd2_dict:
        return True
    return False

【讨论】:

【参考方案9】:

我认为我们可以得到这样的结果


s1 = "listen"
s2 = "silent"
s1=list(s1);s1.sort()
s2 = list(s2);s2.sort()
if s1 == s2:
   print ("Given Strings are Anagram")
else:
   print ("Given String are not anagrams")

【讨论】:

【参考方案10】:

不确定是否是在上面提出的,但我同意了:

def is_anagram(a, b):
    return sorted(a.lower()) == sorted(b.lower())

【讨论】:

【参考方案11】:

只是一个想法:

def check_(arg):
        mark = hash(str(set(sorted(arg))))
        return mark

def ana(s1, s2):
        if check_(s1) != check_(s2):
                pass
        elif len(s1) != len(s2):
                pass
        else:
             print("0 could be anagram of  1".format(s1, s2))

【讨论】:

【参考方案12】:

这对我有用

str1="abcd"
str2="bcad"
word1=[]
word2=[]
for x in range(len(str1)):
    word1.append(str1[x])
for x in range(len(str2)):
    word2.append(str2[x])
if(len(word1)==len(word2)):
    for letter in word1:
        if letter in word2:
            word2.remove(letter)

if len(word2)==0:
    print "anagram"
else:
    print "not anagram"

【讨论】:

【参考方案13】:

    #An anagram is the result of rearranging the letters of a word to produce a new word. Anagrams are case insensitive
    #Examples:
    # foefet is an anagram of toffee
    # Buckethead is an anagram of DeathCubeK

    # The shortest my function style *************************************** 
    def is_anagram1(test, original):
        """Сhecks 'test' is anagram of 'original' strings based on:
        1. length of the both string and length of the sets made from the strings is equivalent
        2. then checks equivalents of sorted lists created from test and original strings

        >>> is_anagram1('Same','same')
        False
        >>> is_anagram1('toffee','foeftt')
        False
        >>> is_anagram1('foefet','toffee')
        True
        >>> is_anagram1("Buuckk",'kkkcuB')
        False
        >>> is_anagram1('Buckethead','DeathCubeK')
        True
        >>> is_anagram1('DeathCubeK','Buckethead')
        True
        """
        # check the length of the both string
        if len(test) != len(original):
            return False

        # check is the strings are the same
        t,o = test.lower(), original.lower()
        if t == o:
            return False

        # check the sorted lists
        return sorted(t) == sorted(o)


    # The final my one line code **************************************
    def is_anagram(test, original):
        """Сhecks 'test' is anagram of 'original' in one line of code

        >>> is_anagram('Same','same')
        False
        >>> is_anagram('toffee','foeftt')
        False
        >>> is_anagram('foefet','toffee')
        True
        >>> is_anagram("Buuckk",'kkkcuB')
        False
        >>> is_anagram('Buckethead','DeathCubeK')
        True
        >>> is_anagram('DeathCubeK','Buckethead')
        True
        """
        return False if len(test) != len(original) or test.lower() == original.lower() else sorted(test.lower()) == sorted(original.lower())

    if __name__ == "__main__":
        import doctest
        doctest.testmod(verbose=True)


### 2 items passed all tests:
### 6 tests in __main__.is_anagram
### 6 tests in __main__.is_anagram1
### 12 tests in 3 items.
### 12 passed and 0 failed.
### Test passed

【讨论】:

【参考方案14】:

最简单的最短解

def anagram(word1, word2):
    return sorted(word1) == sorted(word2)

检查

print(anagram("xyz","zyx"))
>>True

print(anagram("xyz","zyy"))
>>False

【讨论】:

这个在2013年已经been suggested了。【参考方案15】:

这是一个典型的分配解决方案:

def anagram(s1, s2):
""" (str, str) -> bool

Return True if s1 and s2 are anagrams

>>> anagram(s1, s2)
True
"""
    s1 = s1.replace(" ", "")
    s2 = s2.replace(" ", "")

    s1_new = list(s1)
    s2_new = list(s2)

    if len(s1_new) == len(s2_new):
        dupe_found = True
        while dupe_found:
            dupe_found = False
            for i in s1_new:
                for j in s2_new:
                    if i == j:
                        s1_new.remove(i)
                        s2_new.remove(j)
                        dupe_found = True
                        break
                break
    return s1_new == s2_new

【讨论】:

【参考方案16】:
def anagram(a,b):
x=[]
y=[]
for i in a:
    if i!=' ': # This will ignore the spaces in the sentence
        x+=[i] # Adds only letters into a list and ignore the spaces
for i in b:
    if i!=' ':
        y+=[i]
if len(x)==len(y): # if length of two lists are not same, They are not anagrams anyway. So it directly returns False.
    for i in range(len(x)):
        for j in range(len(y)):
            if x[i].lower()==y[j].lower(): 
                y.pop(j) # If the letter matched between first and second list, that letter is poped from that list.
                break
    return len(y)==0 # If the given sentences are anagrams, all the letters are poped out from the second list and function returns True(as the lenght of the second list is 0. If not, function will return False.
return False

字谜(a,b)

【讨论】:

只是一个简短的说明。仅当两个单词组彼此都存在时,此代码实际上才返回 True。如果组中有任何额外的字母,它也会返回 False。【参考方案17】:

Anagram 的 Java 代码

static void anagram(String s1,String s2)
    if(s1.length()!=s2.length())
        System.out.println("not anagram");
        return;
    
    else
        int []arr=new int[256];

        int size=s1.length();
        for(int i=0;i<size;i++)
            arr[s1.charAt(i)]++;
            arr[s2.charAt(i)]--;
        
        for(int i=0;i<256;i++)
            if(arr[i]!=0)
                System.out.println("not anagram");
                return;
                
        
        System.out.println("anagram");
    
    

【讨论】:

【参考方案18】:

这里是使用字典理解的解决方案。

def is_anagram(s1, s2):
    return c:s1.count(c) for c in s1 == c:s2.count(c) for c in s2

【讨论】:

【参考方案19】:

字谜是由相同字符组成的两个不同单词:例如:EAT 和 TEA 同样可以有很多例子。

查看给定两个单词或句子是否是字谜的一个好方法是设置一个大小为 256 的计数器数组,并最初将所有值设置为 0。(如果输入更大,这可能是一个不错的选择,至少比几个单词)现在开始读取第一个字符串(单词或句子),并将其在数组中对应的 ASCII 位置加一。对完整的字符串重复此操作。 现在开始读取第二个字符串并不断减少数组中每个字母的相应 ASCII 计数器。 最后,解析数组;如果所有值都为零,则输入是字谜,否则不是。 以下是注释代码以便更好地理解。

#include<iostream>
#include<string>

using namespace std;

bool is_anagram(string s1, string s2)

    //Following statement chechs the base condition; if either of the strings is empty,                                  
    //return False
    if(s1.length() == 0 || s2.length() == 0)
        return false;

    //initializing the counter array and setting it's values to 0
    int counter[256] = 0;

    //Calculating the lengths of both the strings
    int len1 = s1.length();
    int len2 = s2.length();

    //Following is also a base condition that checks whether the strings are equal in 
    //length, if not we return False
    if(len1 != len2)
        return false;

    //Following for loop increments the values of the counter array for the first  
    //string
    for(int i = 0; i < len1; i++)
    
        counter[s1[i]]++;
    

    //This for loop decrements the values of the counter array for the second string
    for(int i = 0; i < len2; i--)
    
        counter[s2[i]]--;
    
    //Now we check whether the counter array is empty/(or as it was initialized); if               
    //yes then the two strings are anagrams
    for(int i = 0; i < 256; i++)
    
        if(counter[i] != 0)
            return false;
    

    return true;

【讨论】:

我猜第一个 If 应该是if(s1.length() == 0 || s2.length() == 0)。因为您无法将字符串与整数进行比较。 这个问题用 python 标记,这在我看来很像 c++【参考方案20】:

Return True 回答了“w2 是 w1 的子序列的字谜”的问题

解释:在下面的代码中,我们可以回答两个问题:1)两个字符串是否是字谜,2)如果 w2 是 w1 的子序列的字谜。我们使用 O(1) 空间(常数)和 O(n) 时间。字典 d0 可以扩展为包含任何字符,并且我们保持在 O(1) 的空间范围内。

def anagrams(w1,w2):
       d0=chr(i):0 for i in range(ord('a'),ord('z'))
       for char in w1:
           d0[char]+=1
       for char in w2:
           if d0[char]==0:
               return False
           else:
               d0[char]-=1
    return sum([d0[x] for x in d0])==0 #return True (for subseqence anagram)

【讨论】:

虽然您的代码 sn-p 可能会解决问题,但您应该描述您的代码的目的是什么(它如何解决问题)。此外,您可能需要检查***.com/help/how-to-answer 感谢您的评论:从时间和空间复杂性的角度来看,字谜是一个非常有趣的问题:排序最多是 O(n*log(n)) 时间。上面和这里的其他人给出了更好的 O(n) 时间和 O(1) 空间。我添加这个有两个原因:(1.) 包含所有字符很容易。 (只需将跨度“ord('a'), ord('z')”扩展到更宽的范围(保持 O(1) 空间)和 (2.) 最后一行代码可以“返回 True”,如果我们只是想要子串字谜。(上面有人问过,我发现没有人回答)。 sum=0 确保 w1 和 w2 相等。 他的意思是回答。您的答案被标记,因为它是“仅代码”,自动化系统将继续标记它,因为它仍然是“仅代码” 谢谢马修,我包括“摘要”是需要的吗?虽然我还没有看到“摘要”。 艾哈迈德和马修,感谢您的发言。我添加了一个长标题作为描述,但标志仍然是-1。到底是怎么回事?你能帮忙吗?【参考方案21】:

在这种情况下,我们对每个排序的字符串使用两个容器进行检查。

def anagram(s1, s2):
    str1 = ''
    str2 = ''

    for i in s1:
      str1 += i

    for j in s2:
      str2 += j

    if str1 == str2:
      return True

    return False

【讨论】:

【参考方案22】:
str1='ohaha'
str2='hahao1'
set3=set(str1)
set4=set(str2)
if(len(set3.difference(set4))==0 and len(set4.difference(set3))==0):
     print('anagrams')
else:
     print('not anagrams')

【讨论】:

你好@Sai Sudha!您的答案看起来正确,但请为您的代码提供一些上下文/解释。另外请告诉我们您使用的是什么语言。如果是 Python,您的 if 条件中不需要括号。此外,您不需要明确检查差异长度。 bool(set3 - set4)not not (set3 - set4) 应该适合你。 如果您要回答一个已经有 20 个答案的 6 年前的问题,最好介绍您的答案,而不仅仅是提供代码。但是,在这种情况下,您的答案不起作用,因为它没有考虑每个字符有多少。只需以这种方式使用集合,您的代码就会说 hahaoohahahahahahahahaha 是字谜,它们不是。【参考方案23】:

不使用排序的另一种解决方案:

s1 = "aaabbbccc"
s2 = "abcabcabc"

def are_anagram1(s1, s2):
   return [False, True][sum([ord(x) for x in s1]) == sum([ord(x) for x in s2])]

print are_anagram1(s1,s2)

注意:这仅适用于字母而不是数字

【讨论】:

return sum(map(ord, s1)) == sum(map(ord, s2)) 也应该可以工作 是的,s1 和 s2 是可迭代的,谢谢你让它更短, sum(map(ord, "bbf")), sum(map(ord, "acf")) 怎么样,这两个字符串是字谜吗? 不适用于s1 = "ad"s2 = "bc"的情况。 Ascii 的总和相同 (197),但 "ad" and "bc" are NOT Anagrams. 和其他 cmets 中提到的一样,这种方法不起作用,因为不同的字符组可以给出相同的求和结果。【参考方案24】:

我认为最短的方法可以是:

fstr=input("enter first string:")
sstr=input("enter second string:")

if(fstr==sstr[::-1]):
    print("it's anagram")

【讨论】:

这仅在一个字符串与另一个字符串相反时才有效【参考方案25】:
def areAnagram(s1,s2):
    if len(s1) != len(s2):
        return False
    count = [0]*256
    for i in range(len(s1)):
        count[ord(s1[i])] += 1
        count[ord(s2[i])] -= 1
                       
    for x in count:
        if x != 0: 
            return False
    return True

a = input("Enter a string:")
b = input("Enter b string: ")

print(areAnagram(a,b))

【讨论】:

虽然此代码可能会解决问题,但 including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的回答添加解释并说明适用的限制和假设。【参考方案26】:

解决方案:

print('Strings are anagrams' if sorted(input("Enter 1st string: "))== sorted(input("Enter 2nd string: ")) else 'Strings are not anagrams')

【讨论】:

欢迎来到 Stack Overflow!请确保您的解决方案尚未在oneoftheotheranswers 中提出,然后再发布。 @SergeyShubin 我写了这里给出的代码的优化代码。为了展示我如何优化它,我编写了未复制的代码。但是后来我也进行了更改,现在它的代码与这里的任何代码都不匹配! 您可以在回答中解释为什么它比其他人更好:强烈建议您为其他访问者评论解决方案以便更好地理解。它跑得更快吗?还是消耗更少的内存?或者更稳定(在其他算法处理不正确的某些边界情况下有效)?

以上是关于相互检查字符串(Anagrams)的主要内容,如果未能解决你的问题,请参考以下文章

438. Find All Anagrams in a String 438.查找字符串中的所有Anagrams

438. Find All Anagrams in a String 438.查找字符串中的所有Anagrams

查看两个字符串是不是为 Anagrams [C++]

Hackerrank:Sherlock 和 Anagrams [关闭]

Two Strings Are Anagrams

乱序字符串anagrams