匹配子串和字符串列表,如果匹配

时间:2017-11-15 18:12:24

标签: python string pandas

我见过关于这个话题的问题,但大多数都与我的相反。我有一个字符串列表(数据框的列)和一个子字符串列表。我想将每个字符串与子字符串列表进行比较如果它包含一个子字符串,则返回该子字符串,否则打印“不匹配”。

    subs = [cat, dog, mouse]

    df

      Name       Number     SubMatch
     dogfood      1           dog
     catfood      3           cat
     dogfood      2           dog
     mousehouse   1           mouse
     birdseed     1           no match

我当前的输出看起来像这样:

     Name       Number     SubMatch
     dogfood      1           dog
     catfood      3           dog
     dogfood      2           dog
     mousehouse   1           dog
     birdseed     1           dog

我怀疑我的代码只是返回系列中的第一件事,如何将其更改为系列中的正确内容?这是功能:

    def matchy(col, subs):
        for name in col:
            for s in subs:
                if any(s in name for s in subs):
                    return s
                else:
                    return 'No Match'

4 个答案:

答案 0 :(得分:4)

解决这个问题的pandaic方法是根本不使用循环。您可以使用str.extract

完成此操作
p = '({})'.format('|'.join(subs))
df['SubMatch'] = df.Name.str.extract(p, expand=False).fillna('no match')

df

         Name  Number  SubMatch
0     dogfood       1       dog
1     catfood       3       cat
2     dogfood       2       dog
3  mousehouse       1     mouse
4    birdseed       1  no match

答案 1 :(得分:1)

这个怎么样:

def matchy(col, subs):
    for name in col:
        try:
            return next(x for x in subs if x in name)
        except StopIteration:
            return 'No Match'

您的代码存在的问题是您正在检查与any的匹配,但首先返回迭代的第一项(dog)。

编辑赞誉@Coldspeed

def matchy(col, subs):
    for name in col:
        return next(x for x in subs if x in name, 'No match')

答案 2 :(得分:0)

我认为你已经完成了使用嵌套循环复杂化的事情,然后是any测试。这会更好吗:

def matchy(col, subs):
        for name in col:
            for s in subs:
                if s in name:
                    return s
                else:
                    return 'No Match'

答案 3 :(得分:0)

除非缺少对其进行说明的代码,否则您的代码似乎会返回第一次比较的结果,并且实际上不会查看col列表中的任何其他项。如果您更愿意坚持使用嵌套循环,我建议您修改代码:

def matchy(col, subs):
    subMatch = []
    for name in col:
        subMatch.append('No Match')
        for s in subs:
            if s in name:
                subMatch[-1] = s
                break
    return subMatch

这假定col是包含列信息(dogfood,mousehouse等)的字符串列表,subs是包含您要搜索的子字符串的字符串列表。 subMatchmatchy返回的字符串列表,其中包含col中每个项目的搜索结果。

对于我们检查的col中的每个值,我们将'No Match'字符串附加到subMatch,基本上假设我们找不到匹配项。然后我们遍历subs,检查s中是否包含子串name。如果匹配,则subMatch[-1] = s会替换我们附加匹配子字符串的最新'No Match',然后我们会转到col中的下一个项目,因为我们不需要搜索更多值。请注意,subMatch[-1] = s可以替换为其他方法,例如执行subMatch.pop()后跟subMatch.append(s),但此时我认为这更偏向个人。检查col中的所有元素后,系统会返回subMatch,然后您可以按照自己的喜好处理它。