【问题标题】:Find all letters of a string in another string在另一个字符串中查找一个字符串的所有字母
【发布时间】:2018-10-03 03:39:54
【问题描述】:

我正在开展一个项目,该项目可以找到一个单词与许多其他单词的所有字谜。 为此,我需要一个接受 2 个字符串的函数,如果 str1 的所有字母都在 str2 中,则返回 True。

我编写了这段代码:

def almost_anagram(str1, str2):
    tmp = list(str2)
    for i in str1:
            if i in tmp:
                    tmp.remove(i)
            else:
                    return False
    return True

例如:

 almost_anagram("OLLE", "HELLO") = True
 almost_anagram("OOLE", "HELLO") = False

但是有没有更好/更快的方法来做到这一点?

【问题讨论】:

标签: python


【解决方案1】:

你可以使用Counter,它本质上代表一个多集:

import collections

def almost_anagram(word1, word2):
    counter1 = collections.Counter(word1)
    counter2 = collections.Counter(word2)
    return counter1 - counter2 == {}
    # alternatively:
    # return all(counter2[k] >= v for k, v in counter1.items())
    # return counter1 & counter2 == counter1

如果Counter 支持使用< 进行子集测试,代码可以简化为return counter1 < counter2,但不幸的是它不支持。

输出:

>>> almost_anagram("OLLE", "HELLO")
True
>>> almost_anagram("OOLE", "HELLO")
False

【讨论】:

  • 您还可以减去生成的Counter 对象。类似return counter1 - counter2
  • @bro-grammer 你的意思是像return counter1 - counter2 == {}?我想这行得通。谢谢!
  • 是或bool(counter1 - counter2)?
  • 你必须否定它才能得到正确的结果。它可能性能更高,但我更喜欢它更具可读性:)
  • 啊,是的,你是对的!虽然没有否定。它肯定会影响可读性。
【解决方案2】:

使用collections.Counter 对象一次获取字母计数:

import collections    

def almost_anagram(str1, str2):
    str1_cnt, str2_cnt = collections.Counter(str1), collections.Counter(str2)
    return all(k in str2_cnt and str2_cnt[k] == v 
               for k,v in str1_cnt.items())

测试:

print(almost_anagram("OLLE", "HELLO"))  # True
print(almost_anagram("OOLE", "HELLO"))  # False

【讨论】:

  • 您可以减去collections.Counter() 类型的对象。我认为这会使其更快
【解决方案3】:

使用list comprehensionall 应该更快。

例如:

def almost_anagram(str1, str2):
    return all(str2.count(i) >=  str1.count(i) for i in set(str1))

print(almost_anagram("OLLE", "HELLO"))
print(almost_anagram("OOLE", "HELLO"))

输出:

True
False

【讨论】:

  • 你不需要创建一个列表,True if some_condition else False就相当于简单的some_condition...所以基本上all(str2.count(i) >= str1.count(i) for i in str1)
  • @朱利安。谢谢
  • 这可能是非常低效的,因为您每次都在重新计算您的字母,只需在开始时计算一次,然后循环。
  • 我建议在“HELLO”或“hello”的情况下也包含str.lower()
  • @Julien 他只是在重新计算非唯一的,而不是全部。从str1 创建一个集合并进行迭代将是可行的方法。
【解决方案4】:

我更喜欢使用 count() 函数,顺便说一下,您不需要将字符串转换为列表:

def almost_anagram(str1, str2):
    for i in str1:
        if(str1.count(i)==str2.count(i)):
            pass
        else:
            return False
    return True

print(almost_anagram('olle','hello'))
print(almost_anagram('oole','hello')) 

输出:

True
False          

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 2022-06-17
    • 2014-01-25
    相关资源
    最近更新 更多