Python 3+ 是否可以在使用切换器中替换 if in 和 elif

Python 3+ Is It Possible to Replace if in and elif in Using a Switcher

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

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

基本上我正在做的是:

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 中使用切换器?

这是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'} 不是。

尽管本杰明的回答可能是正确的,但它是针对具体情况的,而您的问题具有相当普遍的语气。有一种通用的功能方法(我添加了 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 类型(例如 listtuple),因为将使用具有匹配谓词的第一个动作。

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

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--------

Timingsstr.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)