如果字符串与列表中的字符串匹配,我如何从句子中删除字符串

Posted

技术标签:

【中文标题】如果字符串与列表中的字符串匹配,我如何从句子中删除字符串【英文标题】:How can i remove strings from sentences if string matches with strings in list 【发布时间】:2020-11-11 21:20:27 【问题描述】:

我有一个pandas.Series,上面有这样的句子

0    mi sobrino carlos bajó conmigo el lunes       
1    juan antonio es un tio guay                   
2    voy al cine con ramón                         
3    pepe el panadero siempre se porta bien conmigo
4    martha me hace feliz todos los días 

另一方面,我有一个这样的名字和姓氏列表:

l = ['juan', 'antonio', 'esther', 'josefa', 'mariano', 'cristina', 'carlos']

我想将系列中的句子与列表中的名称相匹配。真实数据比这个例子大得多,所以我认为系列和列表之间的元素比较不会有效,所以我创建了一个包含名称列表中所有字符串的大字符串,如下所示:

'|'.join(l)

我尝试创建一个布尔掩码,稍后允许我通过 true 或 false 值对包含姓名列表中姓名的句子进行索引,如下所示:

series.apply(lambda x: x in '|'.join(l))

但它会返回:

0    False
1    False
2    False
3    False
4    False

这显然不行。

我也尝试过使用str.contains(),但它的行为与我预期的不一样,因为此方法将查看名称列表中是否存在系列中的任何子字符串,这不是我需要的(即我需要一个完全匹配)。

你能指出我正确的方向吗?

非常感谢您

【问题讨论】:

我不知道 panda 是什么,但你可以使用正则表达式,即使它可能更重 当然可以,但我不掌握正则表达式,但如果您提供功能正则表达式,我可以试一试:) @everyone 感谢你们所有人!你提供的所有支持让我不知所措。感谢您的合作:D 【参考方案1】:

如果需要完全匹配,您可以使用单词边界:

series.str.contains('|'.join(rf"\bx\b" for x in l))

对于按列表删除值是使用生成器理解,通过拆分文本仅过滤不匹配的值:

series = series.apply(lambda x: ' '.join(y for y in x.split() if y not in l))
print (series)
                            
0                mi sobrino bajó conmigo el lunes
1                                  es un tio guay
2                           voy al cine con ramón
3  pepe el panadero siempre se porta bien conmigo
4             martha me hace feliz todos los días

【讨论】:

rf 在这里是什么意思? @bigbounty - 正则表达式和 f-string ;) 哦,太好了,我不知道我们可以将两者结合起来。 +1 再次感谢耶兹瑞尔。您能否提供更多关于您的代码的功能的信息? @Miguel2488 - 当然,给我一些时间。【参考方案2】:

正则表达式检查单词是否在开头或结尾或两者之间

df = pd.DataFrame('texts': [
                             'mi sobrino carlos bajó conmigo el lunes',
                             'juan antonio es un tio guay',
                             'voy al cine con ramón',
                             'pepe el panadero siempre se porta bien conmigo',
                             'martha me hace feliz todos los días '
                             ])

names = ['juan', 'antonio', 'esther', 'josefa', 'mariano', 'cristina', 'carlos']

pattern = "|".join([f"^s|s$|\\bs\\b" for s in names])

df[df.apply(lambda x: 
            x.astype(str).str.contains(pattern, flags=re.I)).any(axis=1)]

【讨论】:

【参考方案3】:

一个选项是设置交集:

l = set(['juan', 'antonio', 'esther', 'josefa', 'mariano', 'cristina', 'carlos'])
s.apply(lambda x: len(set(x.split()).intersection(l))>0)

【讨论】:

【参考方案4】:
import re

data = ["mi sobrino carlos bajó conmigo el lunes", "juan antonio es un tio guay", "martha me hace feliz todos los días"]

regexs = ['juan', 'antonio', 'esther', 'josefa', 'mariano', 'cristina', 'carlos']

for regex in regexs:

    for sentence in data:

        if re.match(regex, sentence):

            print True
        
        else:

            print False

我想像这样简单的东西可以工作

cf : https://docs.python.org/fr/3/library/re.html

【讨论】:

注意西班牙语的编码我认为是 UTF-8 完整匹配只需要 "^.*juan.*$"【参考方案5】:

为了完全匹配。试试看;

df.text.str.contains("|".join(l))

否则,只需使用regular expression 将子字符串替换为''。使用列表理解调用substring

df.replace(regex=[x for x in l], value='')
                          

                                   text
0               mi sobrino  bajó conmigo el lunes
1                                  es un tio guay
2                           voy al cine con ramón
3  pepe el panadero siempre se porta bien conmigo
4             martha me hace feliz todos los días

【讨论】:

【参考方案6】:

如果您想要更多的处理灵活性,您可以自定义exact_match 函数,如下所示:

import re 

def exact_match(text, l=l):
    return bool(re.search('|'.join(rf'\bx\b' for x in l), text))

series.apply(exact_match)

输出:

0     True
1     True
2    False
3    False
4    False
dtype: bool

【讨论】:

以上是关于如果字符串与列表中的字符串匹配,我如何从句子中删除字符串的主要内容,如果未能解决你的问题,请参考以下文章

如果匹配列表中的项目,则替换字符串中的项目

从位于字典中的数组中删除与搜索词匹配的所有值(字符串)?

匹配值列表中的字符串并创建新行

替换字符串列表中的子字符串

在两个列表列表中查找匹配的字符串

在python中,如何通过匹配原始列表中的字符串模式从字符串列表中提取子列表