Python中用于两个字符串的变位词测试

3
这是问题:
编写一个名为 test_for_anagrams 的函数,该函数接收两个字符串作为参数,这两个字符串都由字母字符组成,并返回 True 如果这两个字符串是变位词(anagrams),否则返回 False。如果一个字符串可以通过重新排列另一个字符串中的字符并使用所有原始字符串中的字符恰好一次来构造,则两个字符串是变位词。例如,字符串 "Orchestra" 和 "Carthorse" 是变位词,因为每个字符串都可以通过重新排列另一个字符串中的字符并使用其中一个字符串中的所有字符恰好一次来构造。请注意,大小写不重要,即小写字符可以被认为与大写字符相同。
我的代码:
def test_for_anagrams (str_1, str_2):
    str_1 = str_1.lower()
    str_2 = str_2.lower()
    print(len(str_1), len(str_2))
    count = 0
    if (len(str_1) != len(str_2)):
        return (False)
    else:
        for i in range(0, len(str_1)):
            for j in range(0, len(str_2)):
                if(str_1[i] == str_2[j]):
                    count += 1
        if (count == len(str_1)):
            return (True)
        else:
            return (False)


#Main Program
str_1 = input("Enter a string 1: ")
str_2 = input("Enter a string 2: ")
result = test_for_anagrams (str_1, str_2)
print (result)

这里的问题在于当我输入字符串OrchestraCarthorse时,它给出的结果是False。同样的情况也出现在字符串The eyesThey see上。希望能得到帮助。

4
现在没时间调试你的程序,但是这里有一个简短的解决方案:return Counter(str_1.lower()) == Counter(str_2.lower()) 用到了 Python 中 collections 库中的 Counter 方法。 - timgeb
只是一个注释 - 计数器是collections模块的一部分。 我本来想发表这个答案的,但是@timgeb比我快 :) - Andrey Rusanov
您还可以进行排序,然后进行比较。 - pp_
@pp_ 是的,但这个问题可以并且应该在O(n)时间内解决。 - timgeb
@timgeb 我完全同意,把它看作是一个附注。 - pp_
9个回答

6

我是Python的新手,如果我有错误请谅解。

我认为可以采用不同的方法来完成:对给定的字符串进行排序,然后进行比较。

def anagram(a, b):
  # string to list
  str1 = list(a.lower())
  str2 = list(b.lower())

  #sort list
  str1.sort()
  str2.sort()

  #join list back to string
  str1 = ''.join(str1)
  str2 = ''.join(str2)

  return str1 == str2

print(anagram('Orchestra', 'Carthorse'))

从来没有想过这个。太棒了。 - Karan Thakkar

3
问题在于你只是检查字符串中是否存在任何字符匹配,然后递增计数器。你没有考虑已经与另一个字符匹配的字符。这就是为什么以下内容也会失败的原因:
>>> test_for_anagrams('aa', 'aa')
False

即使字符串是相等的(因此也是一个变位词),你正在将第一个字符串的每个 a 与另一个字符串的每个 a 进行匹配,因此您得到了计数为 4 的结果,导致结果为 False
通常情况下,您应该计算每个字符出现的次数,并确保每个字符在每个字符串中出现的次数相同。您可以使用 collections.Counter 对象来计算字符。然后,您只需要检查每个字符串的计数是否相同,这可以通过比较计数器对象(它们只是字典)轻松完成:
from collections import Counter
def test_for_anagrams (str_1, str_2):
    c1 = Counter(str_1.lower())
    c2 = Counter(str_2.lower())
    return c1 == c2

>>> test_for_anagrams('Orchestra', 'Carthorse')
True
>>> test_for_anagrams('aa', 'aa')
True
>>> test_for_anagrams('bar', 'baz')
False

如果导入不符合练习的精神,可以通过循环每个字符串一次来构建自己的计数器,然后进行比较。 - timgeb
谢谢你的解决方案,但我只是在学习Python。我不知道collections或counter是什么。 - Karan Thakkar
@KaranThakkar 在字符串上应用的计数器只是一个字典,它跟踪字符串中每个字符出现的次数。因此,Counter('barbaz')会给你一个字典{'b': 2, 'a': 2, 'r': 1, 'z': 1}Counter只是为您处理计数;但正如timgeb所说,您可以从空字典开始,然后循环遍历字符串并自己计算字符数。 - poke

1

为了完整性:如果只是导入Counter并完成练习不符合练习的精神,您可以使用普通字典来计算字母。

def test_for_anagrams(str_1, str_2):
    counter1 = {}
    for c in str_1.lower():
        counter1[c] = counter1.get(c, 0) + 1
    counter2 = {}
    for c in str_2.lower():
        counter2[c] = counter2.get(c, 0) + 1

    # print statements so you can see what's going on,
    # comment out/remove at will
    print(counter1)
    print(counter2)

    return counter1 == counter2

演示:

print(test_for_anagrams('The eyes', 'They see'))
print(test_for_anagrams('orchestra', 'carthorse'))
print(test_for_anagrams('orchestr', 'carthorse'))

输出:

{' ': 1, 'e': 3, 'h': 1, 's': 1, 't': 1, 'y': 1}
{' ': 1, 'e': 3, 'h': 1, 's': 1, 't': 1, 'y': 1}
True
{'a': 1, 'c': 1, 'e': 1, 'h': 1, 'o': 1, 's': 1, 'r': 2, 't': 1}
{'a': 1, 'c': 1, 'e': 1, 'h': 1, 'o': 1, 's': 1, 'r': 2, 't': 1}
True
{'c': 1, 'e': 1, 'h': 1, 'o': 1, 's': 1, 'r': 2, 't': 1}
{'a': 1, 'c': 1, 'e': 1, 'h': 1, 'o': 1, 's': 1, 'r': 2, 't': 1}
False

0

我已经用基本的方法完成了易于理解的字谜程序。

    def compare(str1,str2):
if((str1==None) or (str2==None)):
    print(" You don't enter string .")
elif(len(str1)!=len(str2)):
    print(" Strings entered is not Anagrams .")
elif(len(str1)==len(str2)):
    b=[]
    c=[]
    for i in str1:
        #print(i)
        b.append(i)
    b.sort()
    print(b)
    for j in str2:
        #print(j)
        c.append(j)
    c.sort()
    print(c)
    if (b==c and b!=[] ):
        print(" String entered is Anargama .")
    else:
        print(" String entered are not Anargama.")
else:
    print(" String entered is not Anargama .")
str1=input(" Enter the first String :")
str2=input(" Enter the second String :")

compare(str1,str2)

0
遍历字符串test并验证字符串test1中是否存在字符,如果存在则将数据存储在字符串value中。 比较value的长度和test1的长度,如果相等则返回True,否则返回False。
def anagram(test,test1):
    value =''
    for data in test:
        if data in test1:
            value +=  data
    if len(value) == len(test1):
        return True
    else:
        return False

anagram("abcd","adbc")

欢迎来到 Stack Overflow!请尽量提供一个关于你的解决方案如何工作的好描述。参见:如何撰写一个好的答案?。谢谢。 - 4b0
这个不行 anagram("bab","bad") == True,应该是 False - Nick stands with Ukraine
我错过了这个测试用例: def anagram(test,test1): value =''for index,data in enumerate(test): if data in test1: value += data if len(value) == len(test1) and sorted(value) == sorted(test1) : return True else: return False - Ravikumar Racha

0
我的解决方案是:

#anagrams

def is_anagram(a, b):
        if sorted(a) == sorted(b):
            return True
        else:
            return False

print(is_anagram("Alice", "Bob"))

0

另一种解决方案:

def test_for_anagrams(my_string1, my_string2):
    s1,s2 = my_string1.lower(), my_string2.lower()
    count = 0
    if len(s1) != len(s2) :
        return False
    for char in s1 :
        if s2.count(char,0,len(s2)) == s1.count(char,0,len(s1)):
            count = count + 1
    return count == len(s1)

0

更加简洁和符合 Python 风格的方法是使用 sorted 和 lower/upper。

您可以先对字符串进行排序,然后使用 lower/upper 使大小写一致以便进行正确比较,具体做法如下:

# Function definition
def test_for_anagrams (str_1, str_2):
    if sorted(str_1).lower() == sorted(str_2).lower():
        return True
    else:
        return False

#Main Program
str_1 = input("Enter a string 1: ")
str_2 = input("Enter a string 2: ")
result = test_for_anagrams (str_1, str_2)
print (result)

-1

定义一个函数anagram(test,test1): test_value = [] 如果test和test1的长度相等: 对于test中的每个元素i: value = test.count(i) == test1.count(i) test_value.append(value) 否则: test_value.append(False)

if False in test_value:
    return  False
else:
    return True

检查test和test1的长度是否匹配,如果匹配,则遍历test字符串并比较test和test1字符串中的字符计数。如果匹配,则将该值存储在字符串中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接