【问题标题】:Identify the matched string from list of strings using any()?使用 any() 从字符串列表中识别匹配的字符串?
【发布时间】:2020-10-01 02:02:16
【问题描述】:

有很多类似的问题都有相同的解决方案:我如何检查我的字符串列表和更大的字符串,看看是否有匹配项? How to check if a string contains an element from a list in PythonHow to check if a line has one of the strings in a list?

我有一个不同的问题:我如何检查我的字符串列表和一个更大的字符串,看看是否有匹配,并隔离字符串,以便我可以执行另一个与匹配字符串相关的字符串操作?

以下是一些示例数据:

| id     | data                |
|--------|---------------------|
| 123131 | Bear Cat Apple Dog  |
| 123131 | Cat Ap.ple Mouse    |
| 231321 | Ap ple Bear         |
| 231321 | Mouse Ap ple Dog    |

最终,我试图找到“apple”['Apple', 'Ap.ple', 'Ap ple'] 的所有实例,虽然匹配哪个并不重要,但我需要能够找出是 Cat 还是 Bear存在于它之前或之后。匹配字符串的位置无关紧要,只是能够确定它之前或之后的内容。

Bear Cat Apple Dog 中,熊在苹果之前,尽管猫在路上。

这是我的示例代码所在的位置:

data = [[123131, "Bear Cat Apple Dog"], ['123131', "Cat Ap.ple Mouse"], ['231321', "Ap ple Bear"], ['231321', "Mouse Ap ple Dog"]] 
df = pd.DataFrame(data, columns = ['id', 'data'])

def matching_function(m): 
     matching_strings = ['Apple', 'Ap.ple', 'Ap ple']

     if any(x in m for x in matching_strings):
          # do something to print the matched string
          return True

df["matched"] = df['data'].apply(matching_function)

在正则表达式中这样做会更好吗?

现在,该函数只返回 true。但是,如果有匹配项,我想它也可以返回 matched_bear_before matched_bear_after 或 Cat 的相同值并将其填充到 df['matched'] 列中。

这是一些示例输出:

| id     | data                | matched |
|--------|---------------------|---------|
| 123131 | Bear Cat Apple Dog  | TRUE    |
| 123131 | Cat Ap.ple Mouse    | TRUE    |
| 231321 | Ap ple Bear         | TRUE    |
| 231321 | Mouse Ap ple Dog    | FALSE   |

【问题讨论】:

  • 所以你想知道其中一个字符串出现在文本中,并且你想在匹配字符串之前和之后提取单词吗?
  • 我会使用正则表达式 - 你可以一口气在苹果旁边测试 cat 和 bear。
  • 是的,我想知道其中一个字符串是否连续出现,先查看之前是否存在Bear或Cat,然后查看之后是否存在
  • @kabaname in "Bear Cat Apple Dog" - 答案是什么?
  • 我已经调整了示例数据和示例输出,以反映我要寻找的内容,对于初学者来说。如果之前和/或之后有匹配,该函数只需返回 true。然而,我正在寻找的关键能力是能够简单地识别一个字符串并在它之前或之后寻找一些东西。

标签: python python-3.x regex pandas


【解决方案1】:

您可以使用以下模式检查CatBear 是否出现在感兴趣的单词之前,在本例中为AppleAp.pleAp ple

^(?:Cat|Bear).*Ap[. ]*ple|Ap[. ]*ple.*(?:Cat|Bear)

要创建满足条件的新数据框列,可以结合mapdf.str.match

>>> df['matched'] = list(map(lambda m: "True" if m else "False", df['data'].str.match('^(?:Cat|Bear).*Ap[. ]*ple|Ap[. ]*ple.*(?:Cat|Bear)')))

或使用numpy.where:

>>> df['matched'] = numpy.where(df['data'].str.match('^(?:Cat|Bear).*Ap[. ]*ple|Ap[. ]*ple.*(?:Cat|Bear)'),'True','False')

将导致:

>>> df
       id                data matched
0  123131  Bear Cat Apple Dog    True
1  123131    Cat Ap.ple Mouse    True
2  231321         Ap ple Bear    True
3  231321    Mouse Ap ple Dog   False

【讨论】:

    【解决方案2】:

    使用Series.str.extractdf['data'] 列中提取三个新列,即keybeforeafter,然后在每个beforeafter 列上使用series.str.findall查找单词前后的所有匹配项:

    import re
    
    keys = ['Apple', 'Ap.ple', 'Ap ple']
    markers = ['Cat', 'Bear']
    
    p =  r'(?P<before>.*?)' + r'(?P<key>' +'|'.join(rf'\b{re.escape(k)}\b' for k in keys) + r')' + r'(?P<after>.*)'
    m = '|'.join(markers)
    
    df[['before', 'key', 'after']] = df['data'].str.extract(p)
    df['before'] = df['before'].str.findall(m)
    df['after'] = df['after'].str.findall(m)
    
    df['matched'] = df['before'].str.len().gt(0) | df['after'].str.len().gt(0)
    

    # print(df)
    
           id                data       before     key   after  matched
    0  123131  Bear Cat Apple Dog  [Bear, Cat]   Apple      []     True
    1  123131    Cat Ap.ple Mouse        [Cat]  Ap.ple      []     True
    2  231321         Ap ple Bear           []  Ap ple  [Bear]     True
    3  231321    Mouse Ap ple Dog           []  Ap ple      []    False
    

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-22
      • 2013-06-18
      相关资源
      最近更新 更多