【问题标题】:How can I tell if a string pattern exists within any element of a set in Python?如何判断 Python 集合的任何元素中是否存在字符串模式?
【发布时间】:2013-08-12 20:33:39
【问题描述】:

我如何询问字符串模式(在本例中为 C)是否存在于该集合的任何元素中,而无需删除它们并查看它们?

这个测试失败了,我不知道为什么。我的猜测是 Python 正在检查集合中是否有任何元素 is C,而不是是否有任何元素 contains C:

n [1]: seto = set()

In [2]: seto.add('C123.45.32')

In [3]: seto.add('C2345.345.32')

In [4]: 'C' in seto
Out[4]: False

我知道我可以迭代它们来进行检查:

In [11]: for x in seto:
    if 'C' in x:
        print(x)
   ....:         
C2345.345.32
C123.45.32

但这不是我在这种情况下想要做的。好的,谢谢你的帮助!

编辑

对不起,这些是集合操作,不是我原帖所暗示的。

【问题讨论】:

  • 如果您不查看每个值,您将如何发现?
  • 迭代可以作为实现完成,但根据我的代码需要,我只想问x in y?
  • 所以您正在寻找部分匹配,而不是完全匹配?编写一个partialIn 函数来遍历列表并进行比较。 in 尝试匹配整个元素。
  • @RobertHarvey 谢谢,我相信这也行。我认为这是因为我对 Python 不够熟悉,还没有考虑到 any() 函数。

标签: python python-3.x iteration


【解决方案1】:
'C' in seto

这将检查 seto 的任何成员是否是确切的字符串 'S'。不是子字符串,而是那个字符串。要检查子字符串,您需要遍历集合并对每个项目执行检查。

any('C' in item for item in seto)

可以轻松更改测试的确切性质。例如,如果您想更严格地确定C 的出现位置:

any(item.startswith('C') for item in seto)

【讨论】:

  • @Houdini 我已经编辑了我的帖子以匹配。集合的解决方案与列表的解决方案相同。
  • 很好,谢谢,我听说过any() 函数,但我还没有机会实现或查看它。看起来是尝试的好时机:)
【解决方案2】:

如果您想使用包含C 的项目子集,则将John's answer 更进一步:

items_with_c = {item for item in seto if 'C' in item}
if items_with_c:
    do_something_with(items_with_c)
else:
    print "No items contain C"

【讨论】:

    【解决方案3】:

    您获得的其他解决方案是正确、可理解且良好的 Python,如果您的集合很小,它们的性能也相当不错。

    但是,使用索引可以更快做你想做的事(当然,在内存和设置时间方面有相当大的开销;TANSTAAFL)。无论您的数据有多大(假设您有足够的内存来保存所有数据),该索引都会保持恒定的性能。如果您要进行大量查找,这可以使您的脚本更快。而且记忆力并没有可能那么糟糕......

    我们将构建一个dict,其中键是索引中项目的每个可能的子字符串,值是包含该子字符串的项目的set

    from collections import defaultdict
    
    class substring_index(defaultdict):
    
        def __init__(self, seq=()):
            defaultdict.__init__(self, set)
            for item in seq:
                self.add(item)
    
        def add(self, item):
            assert isinstance(item, str)   # requires strings
            if item not in self[item]:     # performance optimization for duplicates
                size = len(item) + 1
                for chunk in range(1, size):
                    for start in range(0, size-chunk):
                        self[item[start:start+chunk]].add(item)
    
    seto = substring_index()
    seto.add('C123.45.32')
    seto.add('C2345.345.32')
    
    print(len(seto))      # 97 entries for 2 items, I wasn't kidding about the memory
    

    现在您可以轻松(并且立即)测试以查看索引中是否有任何子字符串:

    print('C' in seto)    # True
    

    或者您可以轻松找到包含特定子字符串的所有字符串:

    print(seto['C'])      # set(['C2345.345.32', 'C123.45.32'])
    

    这可以很容易地扩展到包括“开始于”和“结束于”匹配,或者不区分大小写。

    对于相同想法的内存占用较少的版本,请查看tries

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-11
      • 2011-11-02
      • 2010-11-21
      • 1970-01-01
      • 1970-01-01
      • 2015-06-11
      相关资源
      最近更新 更多