Python:如何比较字符串并忽略空格和特殊字符

20

我希望比较两个字符串,使得比较忽略特殊字符的差异。也就是说,

嗨,这是一个测试

应该与

Hai!这是一个测试 "or" Hai this is a test

匹配。有没有一种方法可以在不修改原始字符串的情况下实现这一点?


5
在这个上下文中,“特殊字符”是什么?重要的是,空格是否被计算在内?因为如果忽略“!”符号,则第一个字符串中只有一个空格,而第二个字符串中则有两个空格。 - Dan Lecocq
8个回答

21

这将在进行比较之前删除标点符号和空格:

In [32]: import string

In [33]: def compare(s1, s2):
    ...:     remove = string.punctuation + string.whitespace
    ...:     return s1.translate(None, remove) == s2.translate(None, remove)

In [34]: compare('Hai, this is a test', 'Hai ! this is a test')
Out[34]: True

12
它不兼容Python3。 - Adam Dobrawy
2
@AdamDobrawy:使用str.maketrans(dict.fromkeys(remove))作为映射(第一个参数)。 - Martijn Pieters
Python3.6 错误 TypeError: translate()接受一个参数, (给出2个) - THAVASI.T

10
>>> def cmp(a, b):
...     return [c for c in a if c.isalpha()] == [c for c in b if c.isalpha()]
... 
>>> cmp('Hai, this is a test', 'Hai ! this is a test')
True
>>> cmp('Hai, this is a test', 'Hai this is a test')
True
>>> cmp('Hai, this is a test', 'other string')
False

这将创建两个临时列表,但不会以任何方式修改原始字符串。


4
可以使用c.isalpha()代替string.letters中的c - DSM

4

Python 3.* 的解决方案

root 给出的解决方案适用于 Python 2.7,但不适用于 Python 3.*

以下是一些快速的解决方法:

  1. 使用相同的解决方案,但为 Python 3.* 进行转换。现在,translate 函数只接受一个参数,即要删除的字符的序数(整数)映射表。

import string

    def compare(s1, s2):
        remove = string.punctuation + string.whitespace
        mapping = {ord(c): None for c in remove}
        print(f'Mapping: \n{mapping}')
        return s1.translate(mapping) == s2.translate(mapping)

    check = compare('Hai, this is a test', 'Hai ! this is a test')
    print(check)

文档


2
通常,你会替换你想要忽略的字符,然后进行比较:
import re
def equal(a, b):
    # Ignore non-space and non-word characters
    regex = re.compile(r'[^\s\w]')
    return regex.sub('', a) == regex.sub('', b)

>>> equal('Hai, this is a test', 'Hai this is a test')
True
>>> equal('Hai, this is a test', 'Hai this@#)($! i@#($()@#s a test!!!')
True

1

为了比较任意数量的字符串是否在字母上等价,

def samealphabetic(*args):
    return len(set(filter(lambda s: s.isalpha(), arg) for arg in args)) <= 1

print samealphabetic('Hai, this is a test',
                     'Hai ! this is a test',
                     'Hai this is a test')

这将打印True。根据您想要返回的无参数内容,应更改<=


0

或许你可以先移除两个字符串中的特殊字符,然后进行比较。

在你的示例中,特殊字符包括“'”、“!”和空格。

因此,针对你的这两个字符串:

a='Hai, this is a test'
b='Hai ! this is a test'
tempa=a.translate(None,',! ')
tempb=b.translate(None,',! ')

然后你可以比较tempa和tempb。


0

既然您提到不想修改原始字符串,您也可以进行原地操作,而且不需要额外的空间。

>>> import string
>>> first = "Hai, this is a test"
>>> second = "Hai ! this is a test"
>>> third = "Hai this is a test"
>>> def my_match(left, right):
    i, j = 0, 0
    ignored = set(string.punctuation + string.whitespace)
    while i < len(left) and j < len(right):
        if left[i] in ignored:
            i += 1
        elif right[j] in ignored:
            j += 1
        elif left[i] != right[j]:
            return False
        else:
            i += 1
            j += 1
    if i != len(left) or j != len(right):
        return False
    return True

>>> my_match(first, second)
True
>>> my_match(first, third)
True
>>> my_match("test", "testing")
False

-1
使用Levenshtein度量来测量两个字符串之间的距离。按分数对您的字符串比较进行排名。选择前n个匹配项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接