0

我知道如何在 Python 中使用字典作为切换器。我不确定如何将一个用于我的具体情况。我想我只需要使用 if、elif 和 else,但希望社区证明我是错误的 :)

我想为字符串中的某些字符创建一个查找/替换函数。该字符串至少是一个句子,但通常更多,并且由许多单词组成。

基本上我正在做的事情如下:

if non-breaking hyphen in string:  # string is a sentence with many words
  replace non-breaking hyphen with dash

elif en dash in string:
  replace en dash with dash

elif em dash in string:
  replace em dash with dash

elif non-breaking space in string:
  replace non-breaking space with space

....等等

我唯一能想到的就是将字符串拆分成单独的子字符串,然后遍历它们,然后字典切换器就可以工作了。但这显然会增加很多额外的处理时间,而使用字典切换器的目的是节省时间。

我到处都找不到关于这个特定主题的任何内容。

有没有办法使用 if in 和 elif in 在 Python 中使用切换器?

4

3 回答 3

4

这是str.translate解决方案

replacements = {
    '\u2011': '-',  # non breaking hyphen
    '\u2013': '-',  # en dash
    '\u2014': '-',  # em dash
    '\u00A0': ' ',  # nbsp
}

trans = str.maketrans(replacements)
new_string = your_string.translate(trans)

请注意,这仅在您想替换输入中的单个字符时才有效。 {'a': 'bb'}是有效的replacements,但{'bb': 'a'}不是。

于 2018-06-20T18:03:00.770 回答
2

只是为了表明正则表达式是一个有效的解决方案,以及一些时间:

replacements = {
    '\u2011': '-',
    '\u2013': '-',
    '\u2014': '-',
    '\u00A0': ' ', 
}

import re
s = "1‑‑‑‑2–––––––3————————"

re.sub(
    '|'.join(re.escape(x) for x in replacements),
    lambda x: replacements[x.group()], s
)
# Result
1----2-------3--------

计时str.trans获胜并且更清洁)

s = "1‑‑‑‑2–––––––3————————"
s *= 10000

%timeit re.sub('|'.join(re.escape(x) for x in replacements), lambda x: replacements[x.group()], s)
90.7 ms ± 182 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [733]: %timeit s.translate(trans)
15.8 ms ± 59.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
于 2018-06-20T18:17:14.323 回答
1

尽管本杰明的回答可能是正确的,但它是针对具体情况的,而您的问题具有相当通用的语气。有一种通用的功能方法(我添加了 Python 3.5 类型注释以使此代码不言自明):

from typing import TypeVar, Callable, Iterable

A = TypeVar('A')
B = TypeVar('B')
Predicate = Callable[[A], bool]
Action = Callable[[A], B]
Switch = Tuple[Predicate, Action]

def switch(switches: Iterable[Switch], default: B, x: A) -> B:
    return next(
        (act(x) for pred, act in switches if pred(x)), default
    )

switches = [
    (lambda x: '\u2011' in x, lambda x: x.replace('\u2011', '-')),
    (lambda x: '\u2013' in x, lambda x: x.replace('\u2013', '-'))
]
a = "I'm–a–string–with–en–dashes"

switch(switches, a, a) # if no switches are matched, return the input

这在您的情况下是多余的,因为您的示例归结为正则表达式操作。请注意,虽然switches可以是任何可迭代的,但您可能希望使用具有可预测迭代顺序的东西,即任何Sequence类型(例如listor tuple),因为将使用具有匹配谓词的第一个动作。

于 2018-06-20T18:12:30.993 回答