Python 3+;是否可以使用交换机更换if in和elif in
我知道如何使用字典作为Python中的切换器。我不知道如何使用我的具体情况之一。我想我只需要使用if、elif和else,但希望社区证明我错了:) 我想为字符串中的某些字符创建一个查找/替换函数。字符串至少是一个句子,但通常更多,由许多单词组成 基本上,我所做的是:Python 3+;是否可以使用交换机更换if in和elif in,python,python-3.x,dictionary,if-statement,switchers,Python,Python 3.x,Dictionary,If Statement,Switchers,我知道如何使用字典作为Python中的切换器。我不知道如何使用我的具体情况之一。我想我只需要使用if、elif和else,但希望社区证明我错了:) 我想为字符串中的某些字符创建一个查找/替换函数。字符串至少是一个句子,但通常更多,由许多单词组成 基本上,我所做的是: if non-breaking hyphen in string: # string is a sentence with many words replace non-breaking hyphen with dash e
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
。。。。诸如此类
我能想到的唯一一件事是将字符串拆分成单独的子字符串,然后循环遍历它们,然后字典切换器就可以工作了。但这显然会增加很多额外的处理时间,使用字典切换器的目的是节省时间
我到处都找不到关于这个特定主题的任何东西
有没有办法在Python中使用if-in和elif-in来使用切换器?下面是解决方案
请注意,这仅在您希望替换输入中的单个字符时有效
{'a':'bb'}
是一个有效的替代品
,但{'bb':'a'}
不是。尽管本杰明的答案可能是正确的,但它是针对具体情况的,而你的问题具有相当普遍的语气。有一种通用的函数方法(我添加了Python3.5类型注释,使此代码具有自解释性):
在您的例子中,这是非常多余的,因为您的示例归结为一个正则表达式操作。请注意,虽然
开关可以是任意iterable,但您可能希望使用具有可预测迭代顺序的东西,即任意序列
类型(例如列表
或元组
),因为将使用具有匹配谓词的第一个操作。只是为了表明regex是一个有效的解决方案,以及一些计时:
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
获胜,而且更干净)
在我看来,正则表达式非常适合。每个if
子句使用一个正则表达式,您不需要任何条件逻辑。@cxw如果每个if
子句需要一个正则表达式,使用正则表达式代替字符串操作有什么意义?您只需要if
语句,而不是elif
。如果字符串
中有一个en破折号
,这并不意味着您也要忽略字符串中的em破折号
,是吗?如果您要替换的每件东西都是一个字符,那么您应该首先使用If
s,但这真的有必要吗?为什么不在不先检查角色是否存在的情况下执行替换<代码>如果s:s=s.replace(“.”,“-”)中的“.”与s=s.replace(“.”,“-”)本身具有相同的行为。@Kevin谢谢,我将改变这一点,因为我所做的是多余的。为了解决这个问题,我们假设我没有替换文本,也没有根据字符串中的内容执行其他操作,是否可以创建字典切换器?我在这里看到的问题是,您将立即替换所有内容,与伪代码实现相反OP@BenjaminToueg我给人的印象是,这是他们真正想要的,即使这不是他们写的。@Patrick Haugh抱歉,我没有你想要的那么清楚。这很难在课文中解释。这就是我想要的,谢谢。这种方法的主要优点是它可以处理多个字符子字符串,您可能需要替换这些字符子字符串。我建议使用'|'.join(替换中x的转义(x)
),以避免在存在要替换的正则表达式相关字符时出现任何问题(并且无需调用键()
)。我不确定'({}).format(…)
部分是否必要,您可以直接使用join
调用中的x | y
作为模式,因为替换工作根本没有捕获组。是的,正在清理正则表达式,感谢您的建议,我将更新good解决方案,但无法读取。如果你添加了一个用法示例,这样人们就可以知道如何使用它,那会有很大帮助。@Aran Fey我对添加一个示例犹豫不决,因为在OP的示例中,这个解决方案是多余的。不过,给你。是的,写一堆lambda是很烦人的。它可能作为配方比函数更有用。使用lambda内联的循环会看起来更干净。@Aran Fey一般来说,使用函数的目的是能够将其部分应用于开关列表(例如,replace\u dashes=partial(开关,开关)
或者甚至partial(开关,开关,默认)
,如果默认值也是固定的)并在不同的位置/表达式中多次重复使用切换器,以实现表达性(在函数编程意义上)代码。
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
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--------
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)