Python 为替换拆分()而生成的函数的意外行为
我编写了一个比split()内置函数性能更好的函数(我知道这不是惯用的python,但我给出了最好的结果),所以当我传递这个参数时:Python 为替换拆分()而生成的函数的意外行为,python,string,split,Python,String,Split,我编写了一个比split()内置函数性能更好的函数(我知道这不是惯用的python,但我给出了最好的结果),所以当我传递这个参数时: better_split("After the flood ... all the colors came out."," .") 我期待着这样的结果: ['After', 'the', 'flood', 'all', 'the', 'colors', 'came', 'out'] 然而,令人惊讶的是,该函数会导致(对我来说)不可理解的行为。当它到达最
better_split("After the flood ... all the colors came out."," .")
我期待着这样的结果:
['After', 'the', 'flood', 'all', 'the', 'colors', 'came', 'out']
然而,令人惊讶的是,该函数会导致(对我来说)不可理解的行为。当它到达最后两个单词时,它不会抑制more“”,而不是添加到结果列表中的“cam”和“out”,而是添加到“come out”,因此,我得到了以下结果:
['After', 'the', 'flood', 'all', 'the', 'colors', 'came out']
有经验的人知道为什么会这样吗?
提前感谢您的帮助
def better_split(text,markersString):
markers = []
splited = []
for e in markersString:
markers.append(e)
for character in text:
if character in markers:
point = text.find(character)
if text[:point] not in character:
word = text[:point]
splited.append(word)
while text[point] in markers and point+1 < len(text):
point = point + 1
text = text[point:]
print 'final splited = ', splited
更简单的解决方案
您的better\u split
函数比您想象的要简单。我已按以下方式实施:
def better_split(s, seps):
result = [s]
def split_by(sep):
return lambda s: s.split(sep)
for sep in seps:
result = sum(map(split_by(sep), result), [])
return filter(None, result) # Do not return empty elements
测验
关于代码的提示
- 您不需要将
更改为标记字符串
,您可以直接通过标记
进行迭代标记字符串
在text[:point]不带字符
时总是point>1
的,所以没有用True
每次在point=text.find(character)
中找不到text
时,将为您提供character
point=-1
- 试着简化代码,Python的一条规则是:“如果有些东西很难解释,那就不是好主意”。不幸的是,您的代码甚至很难阅读,其中包含大量冗余语句,加上看起来应该与实际工作方式不同的语句(例如,使用
获取分隔符的位置,然后在不检查获取切片的情况下使用它str.find
better\u split
函数比您想象的要简单。我已将其实现为:
def better_split(s, seps):
result = [s]
def split_by(sep):
return lambda s: s.split(sep)
for sep in seps:
result = sum(map(split_by(sep), result), [])
return filter(None, result) # Do not return empty elements
测验
关于代码的提示
- 您不需要将
更改为标记字符串
,您可以直接通过标记
进行迭代标记字符串
在text[:point]不带字符
时总是point>1
的,所以没有用True
每次在point=text.find(character)
中找不到text
时,将为您提供character
point=-1
- 试着简化你的代码,Python的一条规则说:“如果有些东西很难解释,那是个坏主意”。不幸的是,你的代码甚至很难阅读,包含了很多冗余语句,加上看起来应该与实际工作方式不同的语句(例如,使用
获取分离器的位置,然后在不检查获取切片的情况下使用它str.find
- 问题在于:
for character in text:
是在初始字符串中的字符(文本的原始值)上循环,而这:
point = text.find(character)
在当前字符串中搜索分隔符-当前值text
。因此,函数的一部分操作假定您一次处理一个分隔符字符;也就是说,它假定每当您在原始text
的循环中遇到分隔符字符时,这是第一个deli当前文本中的斜接字符
同时,这:
while text[point] in markers and point+n < len(text):
point = point + 1
text = text[point:]
如您所见,您正在处理的分隔符最终并不是您拆分的分隔符
解决方案只是删除允许您一次跳过多个分隔符的逻辑-即,更改以下内容:
while text[point] in markers and point+n < len(text):
point = point + 1
text = text[point:]
问题在于:
for character in text:
是在初始字符串中的字符(文本的原始值)上循环,而这:
point = text.find(character)
在当前字符串中搜索分隔符-当前值text
。因此,函数的一部分操作假定您一次处理一个分隔符字符;也就是说,它假定每当您在原始text
的循环中遇到分隔符字符时,这是第一个deli当前文本中的斜接字符
同时,这:
while text[point] in markers and point+n < len(text):
point = point + 1
text = text[point:]
如您所见,您正在处理的分隔符最终并不是您拆分的分隔符
解决方案只是删除允许您一次跳过多个分隔符的逻辑-即,更改以下内容:
while text[point] in markers and point+n < len(text):
point = point + 1
text = text[point:]
关键是,迭代器是在以下行中创建的,并成为常量:
for character in text:
被处决了,
但你的目标是在每次for循环后,对更改后的文本进行iter
因此,解决方案是,将for循环移动到内部函数中,并递归使用它:
def better_split(text,markersString):
# simple and better way for 'for e in markerString...'
markers = list(markersString)
splited = []
# there is no need to assign variable n, we all know it should be 1
# n = 1
def iter_text(text):
# check if text is an empty string,
# NOTE this `text` will cover `text` in upper function as to local scope,
# so it's actually the text everytime iter_text() get,
# not the one better_split() get.
if not text:
return
# [UPDATES 2012-03-17 01:07 EST]
# add a flag to judge if there are markers in `text`
_has_marker = False
for character in text:
if character in markers:
# set `_has_marker` to True to indicate `text` has been handled
_has_marker = True
point = text.find(character)
word = text[:point]
splited.append(word)
# check if text[point] is legal, to prevent raising of IndexError
while point + 1 <= len(text) and text[point] in markers:
point = point + 1
text = text[point:]
# break the loop when you find a marker
# and change `text` according to it,
# so that the new loop will get started with changed `text`
break
# if no marker was found in `text`, add the whole `text` to `splited`
if not _has_marker:
splited.append(text)
else:
iter_text(text)
iter_text(text)
print 'final splited = ', splited
关键是,迭代器是在以下行中创建的,并成为常量:
for character in text:
被处决了,
但你的目标是在每次for循环后,对更改后的文本进行iter
因此,解决方案是,将for循环移动到内部函数中,并递归使用它:
def better_split(text,markersString):
# simple and better way for 'for e in markerString...'
markers = list(markersString)
splited = []
# there is no need to assign variable n, we all know it should be 1
# n = 1
def iter_text(text):
# check if text is an empty string,
# NOTE this `text` will cover `text` in upper function as to local scope,
# so it's actually the text everytime iter_text() get,
# not the one better_split() get.
if not text:
return
# [UPDATES 2012-03-17 01:07 EST]
# add a flag to judge if there are markers in `text`
_has_marker = False
for character in text:
if character in markers:
# set `_has_marker` to True to indicate `text` has been handled
_has_marker = True
point = text.find(character)
word = text[:point]
splited.append(word)
# check if text[point] is legal, to prevent raising of IndexError
while point + 1 <= len(text) and text[point] in markers:
point = point + 1
text = text[point:]
# break the loop when you find a marker
# and change `text` according to it,
# so that the new loop will get started with changed `text`
break
# if no marker was found in `text`, add the whole `text` to `splited`
if not _has_marker:
splited.append(text)
else:
iter_text(text)
iter_text(text)
print 'final splited = ', splited
better\u split()
不是一个好名字。如何“更好”,以什么方式
yourmodule.split()
足以将其与任何其他split()函数区分开来
您可以使用以下方法实现它:
如果不允许使用映射
,过滤器
,则可以轻松替换它们:
“|”。连接(映射(关于转义,分隔符))
:
过滤器(无,重新拆分(文本))
:
更好\u split()
不是一个好名字。如何“更好”,以什么方式
yourmodule.split()
足以将其与任何其他split()函数区分开来
您可以使用以下方法实现它:
如果不允许使用映射
,过滤器
,则可以轻松替换它们:
“|”。连接(映射(关于转义,分隔符))
:
过滤器(无,重新拆分(文本))
:
def spli(str,sep=''):
索引=0
字符串=“”
列表=[]
而索引defspli(str,sep=''):
索引=0
字符串=“”
列表=[]
而IndexHanks,Tadeck,为这个漂亮的代码示例!
"|".join(re.escape(s) for s in separators)
[s for s in re_sep.split(text) if s]
def spli(str,sep=' '):
index=0
string=''
list=[]
while index<len(str):
if(str[index] not in sep):
string+=str[index]
elif(str[index] in sep):
list.append(string)
string=''
index+=1
if string:list.append(string)
return(list)
n='hello'
print(spli(n))
output:
['h','e','l','l','o']