为啥 split() 结果中返回空字符串?

Posted

技术标签:

【中文标题】为啥 split() 结果中返回空字符串?【英文标题】:Why are empty strings returned in split() results?为什么 split() 结果中返回空字符串? 【发布时间】:2011-01-12 22:30:08 【问题描述】:

'/segment/segment/'.split('/') 返回['', 'segment', 'segment', ''] 有什么意义?

注意空元素。如果您要拆分的分隔符恰好位于字符串的第一个位置且位于字符串的最后,那么从每一端返回空字符串会给您带来什么额外的价值?

【问题讨论】:

我也有同样的问题,搜了很久。现在我明白空的结果真的很重要。感谢您的提问。 一种解决方案是使用strip()在拆分之前从字符串中去除前导和尾随拆分字符:'/segment/segment/'.strip('/').split('/') 该解决方案不适用于'/segment//segment/'.split('/') 【参考方案1】:

更一般地,要删除在split() 结果中返回的空字符串,您可能需要查看filter 函数。

例子:

f = filter(None, '/segment/segment/'.split('/'))
s_all = list(f)

返回

['segment', 'segment']

【讨论】:

如果您更喜欢列表推导:[x for x in '/segment/segment/'.split('/') if x]【参考方案2】:

str.split 补充 str.join,所以

"/".join(['', 'segment', 'segment', ''])

让你回到原来的字符串。

如果不存在空字符串,则join() 之后的第一个和最后一个'/' 将丢失。

【讨论】:

【参考方案3】:

考虑这个最小的例子:

>>> '/'.split('/')
['', '']

split 必须给出分隔符'/' 前后的内容,但没有其他字符。所以它必须给你一个空字符串,它在技术上在'/'之前和之后,因为'' + '/' + '' == '/'

【讨论】:

【参考方案4】:

x.split(y) 总是返回一个1 + x.count(y) 项目列表是一种宝贵的规律——正如@gnibbler 已经指出的那样,它使splitjoin 彼此完全相反(显然应该如此),它还精确映射各种分隔符连接记录的语义(例如csv 文件行[[引用问题网]],Unix 中来自/etc/group 的行等),它允许(如@Roman's提到的答案)轻松检查(例如)绝对路径和相对路径(在文件路径和 URL 中)等等。

另一种看待它的方式是,您不应该无所事事地肆无忌惮地将信息扔出窗外。使x.split(y) 等同于x.strip(y).split(y) 会得到什么?没什么,当然——当你的意思是第二种形式时,它很容易使用,但如果第一种形式被任意认为是第二种形式,那么当你 do 时你会有很多工作要做strong> 想要第一个(正如上一段所指出的,这绝非罕见)。

但实际上,从数学规律的角度思考是自学设计可通过 API 的最简单、最通用的方法。举一个不同的例子,对于任何有效的xy x == x[:y] + x[y:] 来说,这一点非常重要——这立即表明了为什么切片的一个极端应该被排除。您可以制定的不变量断言越简单,所产生的语义就越有可能是您在现实生活中使用的 - 这是数学在处理宇宙方面非常有用的神秘事实的一部分。

尝试为 split 方言制定不变量,其中前导和尾随定界符是特殊情况... 987654335@ -- 愚蠢的领先 x and 就是为什么你经常发现自己在编码 not x or x.isspace(),以回到 应该 被设计到 is... 字符串方法中的简单性(其中一个空字符串“是”你想要的任何东西——与街头人的马意识相反,也许 [[empty sets,like zero &c,总是让大多数人感到困惑;-)]],但完全符合明显的好-精炼数学常识!-)。

【讨论】:

【参考方案5】:

这里有两点需要考虑:

期望'/segment/segment/'.split('/') 的结果等于['segment', 'segment'] 是合理的,但这会丢失信息。如果split() 以你想要的方式工作,如果我告诉你a.split('/') == ['segment', 'segment'],你就无法告诉我a 是什么。 'a//b'.split() 的结果应该是什么? ['a', 'b']?,或['a', '', 'b']?即,split() 是否应该合并相邻的分隔符?如果应该,那么将很难解析由字符分隔的数据,并且某些字段可能为空。我相当肯定有很多人确实想要上述案例的结果中的空值!

最后归结为两件事:

一致性:如果我有n 分隔符,在a 中,我会在split() 之后得到n+1 值。

应该可以做复杂的事情,容易做简单的事情:如果你想忽略split()导致的空字符串,你总是可以这样做:

def mysplit(s, delim=None):
    return [x for x in s.split(delim) if x]

但如果不想忽略空值,应该可以。

语言必须选择split() 的一种定义——默认情况下有太多不同的用例来满足每个人的要求。我认为 Python 的选择是一个不错的选择,也是最符合逻辑的。 (顺便说一句,我不喜欢 C 的 strtok() 的原因之一是因为它合并了相邻的分隔符,因此很难用它进行认真的解析/标记化。)

有一个例外:a.split() 没有参数会挤压连续的空白,但可以说在这种情况下这是正确的做法。如果你不想要这种行为,你可以随时a.split(' ')

【讨论】:

对于那些想知道是核对重复的空格,然后拆分,还是拆分并且只采用非空字符串更快的人,这就是我得到的:python3 -m timeit "import re ; re.sub(' +', ' foo bar baz ', '').split(' ')" -> 每个循环 875 纳秒; python3 -m timeit "[token for token in ' foo bar baz '.split(' ') if token]" -> 每个循环 616 纳秒【参考方案6】:

好吧,它让您知道那里有一个分隔符。因此,看到 4 个结果让您知道您有 3 个分隔符。这使您能够使用此信息做任何您想做的事情,而不是让 Python 删除空元素,然后让您在需要时手动检查开始或结束分隔符。

简单示例:假设您要检查绝对文件名和相对文件名。这样您就可以通过拆分完成所有操作,而不必检查文件名的第一个字符是什么。

【讨论】:

【参考方案7】:

我不确定您在寻找什么样的答案?你得到三个匹配,因为你有三个分隔符。如果您不想要那个空的,只需使用:

'/segment/segment/'.strip('/').split('/')

【讨论】:

-1 因为你得到了四场比赛而不是三场比赛,而且这并不能真正回答问题。 +1 来抵消负面影响。他没有说你会得到三个结果。他对“三个分隔符”说“三个匹配”,这对我来说听起来很合乎逻辑。但是,您不会得到任何东西的“四场比赛”。不过,您确实会在结果中返回“四个元素”。此外,它并没有直接回答“为什么”,但它确实提供了一种简单的方法来获得他真正想要的东西......我认为这不值得一票。如果您要挑剔某人(不赞成投票,不少于),请更加小心!干杯! 8^) @wasatchwizard 感谢您的澄清。我感谢您的更正和建议。很遗憾,现在我的投票已锁定,无法更改。

以上是关于为啥 split() 结果中返回空字符串?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 django page cms get_absolute_url 返回一个空字符串?

为啥 Perl 使用空字符串来表示 boolean false 值?

为啥 javascript this.style[property] 返回一个空字符串? [复制]

为啥 javascript this.style[property] 返回一个空字符串? [复制]

为啥替换在空字符串上不返回任何内容

为啥 curl_exec($url) 返回空字符串