按单词拆分(不区分大小写)
Split by a word (case insensitive)
如果我想带
"hi, my name is foo bar"
并在 "foo"
上拆分,并让该拆分不区分大小写(在 "foO"
、"FOO"
、"Foo"
等中的任何一个上拆分),应该我愿意?请记住,虽然我希望拆分不区分大小写,但我也确实希望保持字符串其余部分的大小写敏感。
所以如果我有:
test = "hi, my name is foo bar"
print test.split('foo')
print test.upper().split("FOO")
我会得到
['hi, my name is ', ' bar']
['HI, MY NAME IS ', ' BAR']
分别。
但我想要的是:
['hi, my name is ', ' bar']
每一次。目标是保持原始字符串的大小写敏感性,除了我要拆分的内容。
所以如果我的测试字符串是:
"hI MY NAME iS FoO bar"
我想要的结果是:
['hI MY NAME iS ', ' bar']
您可以使用re.split
function with the re.IGNORECASE
flag(或简称re.I
):
>>> import re
>>> test = "hI MY NAME iS FoO bar"
>>> re.split("foo", test, flags=re.IGNORECASE)
['hI MY NAME iS ', ' bar']
>>>
您还可以搜索一些东西并获取关键字的起始位置。我会推荐并用 "substring" 方法将其删除。 (我来自 C#,所以我不知道这种语言的方法是什么)
这不是确切答案,而是基于问题的解决方案。
在网上搜索了一段时间后,我实现了以下内容。
这是我的自定义标签(参见 how to do it)。
from django.template.defaultfilters import register
from django.utils.html import escape
from django.utils.safestring import mark_safe
@register.simple_tag
def highlight(string, entry, prefix, suffix):
string = escape(string)
entry = escape(entry)
string_upper = string.upper()
entry_upper = entry.upper()
result = ''
length = len(entry)
start = 0
pos = string_upper.find(entry_upper, start)
while pos >= 0:
result += string[start:pos]
start = pos + length
result += prefix + string[pos:start] + suffix
pos = string_upper.find(entry_upper, start)
result += string[start:len(string)]
return mark_safe(result)
它接受不安全的字符串和 returns 转义结果。
这样使用:
<span class="entityCode">{% highlight entity.code search_text '<span class="highlighted">' '</span>' %}</span>
我使用嵌套<span>
来继承所有的样式。它显示类似
一个非常不合理的解决方案,当你想精确地分割一次时(奖励:它也保留了找到的分隔符的大小写,所以你知道你实际分割的是什么):
teststr = "hI MY NAME iS FoO bar"
blen, _, alen = map(len, teststr.casefold().partition("foo"))
before, sep, after = teststr[:blen], teststr[blen:-alen], teststr[-alen:]
print([before, sep, after])
哪个输出(包括字符串的原始分隔符,如果你愿意可以丢弃):
['hI MY NAME iS ', 'FoO', ' bar']
类似的代码可以用 teststr.casefold().index("foo")
加上基于索引和分隔符长度的切片来编写;我喜欢 partition
为我做更多的工作(无论分隔符是否出现在字符串中,都可以无分支地工作),但这纯粹是个人喜好。
这可以适应拆分任意次数(但丢失分隔符,因为 str.split
丢弃它们,不像 str.partition
)与 itertools
助手:
from itertools import accumulate, pairwise # On 3.10+, pairwise is a built-in, pre-3.10, you'd use the pairwise recipe from itertools docs
# accumulate only accepts an initial argument
# on 3.8+, but you can fake it with chain before that
teststr = "hI MY NAME iS FoO bar aNd I LOvE fOoD!"
components = [teststr[s+i*3:e+i*3]
for i, (s, e) in enumerate(pairwise(accumulate(map(len, teststr.casefold().split("foo")), initial=0)))]
print(components)
产生:
['hI MY NAME iS ', ' bar aNd I LOvE ', 'D!']
说清楚,第一种方案不合理,第二种方案很疯狂。我post这主要是为了说明;在这种情况下 non-regex 解决方案是疯狂的,所以即使你同意我的观点,应该尽可能避免使用正则表达式,但在这种情况下还是硬着头皮使用它们。
如果我想带
"hi, my name is foo bar"
并在 "foo"
上拆分,并让该拆分不区分大小写(在 "foO"
、"FOO"
、"Foo"
等中的任何一个上拆分),应该我愿意?请记住,虽然我希望拆分不区分大小写,但我也确实希望保持字符串其余部分的大小写敏感。
所以如果我有:
test = "hi, my name is foo bar"
print test.split('foo')
print test.upper().split("FOO")
我会得到
['hi, my name is ', ' bar']
['HI, MY NAME IS ', ' BAR']
分别。
但我想要的是:
['hi, my name is ', ' bar']
每一次。目标是保持原始字符串的大小写敏感性,除了我要拆分的内容。
所以如果我的测试字符串是:
"hI MY NAME iS FoO bar"
我想要的结果是:
['hI MY NAME iS ', ' bar']
您可以使用re.split
function with the re.IGNORECASE
flag(或简称re.I
):
>>> import re
>>> test = "hI MY NAME iS FoO bar"
>>> re.split("foo", test, flags=re.IGNORECASE)
['hI MY NAME iS ', ' bar']
>>>
您还可以搜索一些东西并获取关键字的起始位置。我会推荐并用 "substring" 方法将其删除。 (我来自 C#,所以我不知道这种语言的方法是什么)
这不是确切答案,而是基于问题的解决方案。 在网上搜索了一段时间后,我实现了以下内容。
这是我的自定义标签(参见 how to do it)。
from django.template.defaultfilters import register
from django.utils.html import escape
from django.utils.safestring import mark_safe
@register.simple_tag
def highlight(string, entry, prefix, suffix):
string = escape(string)
entry = escape(entry)
string_upper = string.upper()
entry_upper = entry.upper()
result = ''
length = len(entry)
start = 0
pos = string_upper.find(entry_upper, start)
while pos >= 0:
result += string[start:pos]
start = pos + length
result += prefix + string[pos:start] + suffix
pos = string_upper.find(entry_upper, start)
result += string[start:len(string)]
return mark_safe(result)
它接受不安全的字符串和 returns 转义结果。
这样使用:
<span class="entityCode">{% highlight entity.code search_text '<span class="highlighted">' '</span>' %}</span>
我使用嵌套<span>
来继承所有的样式。它显示类似
一个非常不合理的解决方案,当你想精确地分割一次时(奖励:它也保留了找到的分隔符的大小写,所以你知道你实际分割的是什么):
teststr = "hI MY NAME iS FoO bar"
blen, _, alen = map(len, teststr.casefold().partition("foo"))
before, sep, after = teststr[:blen], teststr[blen:-alen], teststr[-alen:]
print([before, sep, after])
哪个输出(包括字符串的原始分隔符,如果你愿意可以丢弃):
['hI MY NAME iS ', 'FoO', ' bar']
类似的代码可以用 teststr.casefold().index("foo")
加上基于索引和分隔符长度的切片来编写;我喜欢 partition
为我做更多的工作(无论分隔符是否出现在字符串中,都可以无分支地工作),但这纯粹是个人喜好。
这可以适应拆分任意次数(但丢失分隔符,因为 str.split
丢弃它们,不像 str.partition
)与 itertools
助手:
from itertools import accumulate, pairwise # On 3.10+, pairwise is a built-in, pre-3.10, you'd use the pairwise recipe from itertools docs
# accumulate only accepts an initial argument
# on 3.8+, but you can fake it with chain before that
teststr = "hI MY NAME iS FoO bar aNd I LOvE fOoD!"
components = [teststr[s+i*3:e+i*3]
for i, (s, e) in enumerate(pairwise(accumulate(map(len, teststr.casefold().split("foo")), initial=0)))]
print(components)
产生:
['hI MY NAME iS ', ' bar aNd I LOvE ', 'D!']
说清楚,第一种方案不合理,第二种方案很疯狂。我post这主要是为了说明;在这种情况下 non-regex 解决方案是疯狂的,所以即使你同意我的观点,应该尽可能避免使用正则表达式,但在这种情况下还是硬着头皮使用它们。