Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用多个分隔符高效拆分字符串并保留每个分隔符?_Python_String - Fatal编程技术网

Python 使用多个分隔符高效拆分字符串并保留每个分隔符?

Python 使用多个分隔符高效拆分字符串并保留每个分隔符?,python,string,Python,String,我需要使用string.parantion和string.whitespace中的每个字符作为分隔符来分割数据字符串 此外,我需要分隔符保留在输出列表中,在它们在字符串中分隔的项目之间 比如说, "Now is the winter of our discontent" 应输出: ['Now', ' ', 'is', ' ', 'the', ' ', 'winter', ' ', 'of', ' ', 'our', ' ', 'discontent'] 我不知道如何在不使用大量嵌套循环的情况

我需要使用
string.parantion
string.whitespace
中的每个字符作为分隔符来分割数据字符串

此外,我需要分隔符保留在输出列表中,在它们在字符串中分隔的项目之间

比如说,

"Now is the winter of our discontent"
应输出:

['Now', ' ', 'is', ' ', 'the', ' ', 'winter', ' ', 'of', ' ', 'our', ' ', 'discontent']
我不知道如何在不使用大量嵌套循环的情况下做到这一点,因为嵌套循环的速度慢得令人无法接受。我怎么做

import re
import string

p = re.compile("[^{0}]+|[{0}]+".format(re.escape(
    string.punctuation + string.whitespace)))

print p.findall("Now is the winter of our discontent")
我不太喜欢使用regexp解决所有问题,但如果您希望它快速、简短,我认为您在这方面没有太多选择

我将解释regexp,因为您不熟悉它:

  • […]
    表示方括号内的任何字符
  • [^…]
    表示不在方括号内的任何字符
  • +
    后面表示前面的一个或多个内容
  • x | y
    表示匹配
    x
    y
因此,regexp匹配1个或多个字符,其中要么所有字符都必须是标点符号和空格,要么没有。
findall
方法查找模式的所有非重叠匹配项。

尝试以下操作:

from string import punctuation, whitespace

s = "..test. and stuff"

f = lambda s, c: s + ' ' + c + ' ' if c in punctuation else s + c
l =  sum([reduce(f, word).split() for word in s.split()], [])

print l
重新导入
re.split(“(['+re.escape(string.标点符号+string.whitespace)+']+”,“现在是我们不满的冬天”)
解释来自:

如果模式中使用了捕获括号,那么模式中所有组的文本也将作为结果列表的一部分返回


根据所处理的文本,您可以将分隔符的概念简化为“字母和数字以外的任何内容”。如果可行,您可以使用以下正则表达式解决方案:

re.findall(r'[a-zA-Z\d]+|[^a-zA-Z\d]', text)
这假设您希望在每个分隔符字符上拆分,即使它们连续出现,因此
'foo..bar'
将变成
['foo','.','.','bar']
。如果您希望使用
['foo','..,'bar']
,请使用
[a-zA-Z\d]+|[^a-zA-Z\d]+
(唯一的区别是在末尾添加
+

线性(
O(n)
)时间:

假设您有一个字符串:

original = "a, b...c    d"
首先将所有分隔符转换为空格:

splitters = string.punctuation + string.whitespace
trans = string.maketrans(splitters, ' ' * len(splitters))
s = original.translate(trans)
现在
s==“a b c d”
。现在,您可以使用
itertools.groupby
在空格和非空格之间切换:

result = []
position = 0
for _, letters in itertools.groupby(s, lambda c: c == ' '):
    letter_count = len(list(letters))
    result.append(original[position:position + letter_count])
    position += letter_count
现在,
result==['a'、'、'b'、'…'、'c'、''d']
,这就是您所需要的。

我的想法:

from string import whitespace, punctuation
import re

pattern = re.escape(whitespace + punctuation)
print re.split('([' + pattern + '])', 'now is the winter of')

与其他方法不同的非正则表达式方法:

>>> import string
>>> from itertools import groupby
>>> 
>>> special = set(string.punctuation + string.whitespace)
>>> s = "One two  three    tab\ttabandspace\t end"
>>> 
>>> split_combined = [''.join(g) for k, g in groupby(s, lambda c: c in special)]
>>> split_combined
['One', ' ', 'two', '  ', 'three', '    ', 'tab', '\t', 'tabandspace', '\t ', 'end']
>>> split_separated = [''.join(g) for k, g in groupby(s, lambda c: c if c in special else False)]
>>> split_separated
['One', ' ', 'two', '  ', 'three', '    ', 'tab', '\t', 'tabandspace', '\t', ' ', 'end']
我想可以使用
dict.fromkeys
get
而不是
lambda

[编辑]

一些解释:

groupby
接受两个参数,一个iterable和一个(可选)keyfunction。它循环遍历iterable并将其与keyfunction的值分组:

>>> groupby("sentence", lambda c: c in 'nt')
<itertools.groupby object at 0x9805af4>
>>> [(k, list(g)) for k,g in groupby("sentence", lambda c: c in 'nt')]
[(False, ['s', 'e']), (True, ['n', 't']), (False, ['e']), (True, ['n']), (False, ['c', 'e'])]

对于我们合并分离器的情况
.get
返回
None
,如果该值不在目录中。

对于任意分隔符集合:

def separate(myStr, seps):
    answer = []
    temp = []
    for char in myStr:
        if char in seps:
            answer.append(''.join(temp))
            answer.append(char)
            temp = []
        else:
            temp.append(char)
    answer.append(''.join(temp))
    return answer

In [4]: print separate("Now is the winter of our discontent", set(' '))
['Now', ' ', 'is', ' ', 'the', ' ', 'winter', ' ', 'of', ' ', 'our', ' ', 'discontent']

In [5]: print separate("Now, really - it is the winter of our discontent", set(' ,-'))
['Now', ',', '', ' ', 'really', ' ', '', '-', '', ' ', 'it', ' ', 'is', ' ', 'the', ' ', 'winter', ' ', 'of', ' ', 'our', ' ', 'discontent']

希望这有帮助

您可能想使用
re.escape(string.标点符号+string.whitespace)
,否则我认为您的字符类将在
]早期结束
。我认为它不适用于“.现在是我们不满的冬天”@F.J修复了。和
“。现在是我们不满的冬天”
对我来说很有效。@lazyr不应该“..”是“,”@blz正如我所说,我不太喜欢regexp解决方案。DSM的回答令人印象深刻,我怀疑这是除regexps之外,您在速度方面所能期望的最好结果(如果不计算regexp的编译速度,这个解决方案比他的快4.5倍。包括compile,它的速度差不多相同。)连续空格的丑陋行为:
re.split(r'(),'*2)
导致
['','','',''现在应该更好地处理@F.J连续空格/分隔符。连续分隔符的丑陋行为:
re.split('(['+pattern+']),“…”
会导致
['','','','',']
或另一个选项,而不是lambda(尽管很难看)
groupby(s,special.)
…@JonClements:是的,我想在我使用特殊方法之前我应该先使用dict.:
partial(contains,special)
then?;)@DSM,使用dict而不是lambda有什么好处?
special=dict.fromkeys(string.标点符号+string.whitespace,True);split\u combined=[''。在groupby中加入(g)代表k,g(s,special.get)]
是我认为DSM的意思…@blz[wrt.fromkeys]当您使用
string.percentration+string.whitespace
作为
seps
参数时,这可能会开始变慢——对于每个字符,您都在线性时间内搜索分隔符列表。如果您将它们作为
集传递,我猜不会。因为您接受了DSM的答案,您打算用于连续标点字符要保持分组吗?@johnthexiii,我接受了它,因为它没有使用
re
。将连续分隔符分组的选项是一个额外的好处,尽管我相信使用regex也可以轻松完成。
>>> special = dict.fromkeys(string.punctuation + string.whitespace, True)
>>> s = "One two  three    tab\ttabandspace\t end"
>>> [''.join(g) for k,g in groupby(s, special.get)]
['One', ' ', 'two', '  ', 'three', '    ', 'tab', '\t', 'tabandspace', '\t ', 'end']
def separate(myStr, seps):
    answer = []
    temp = []
    for char in myStr:
        if char in seps:
            answer.append(''.join(temp))
            answer.append(char)
            temp = []
        else:
            temp.append(char)
    answer.append(''.join(temp))
    return answer

In [4]: print separate("Now is the winter of our discontent", set(' '))
['Now', ' ', 'is', ' ', 'the', ' ', 'winter', ' ', 'of', ' ', 'our', ' ', 'discontent']

In [5]: print separate("Now, really - it is the winter of our discontent", set(' ,-'))
['Now', ',', '', ' ', 'really', ' ', '', '-', '', ' ', 'it', ' ', 'is', ' ', 'the', ' ', 'winter', ' ', 'of', ' ', 'our', ' ', 'discontent']