将字符串拆分为具有多个单词边界定界符的单词


671

我认为我想做的是一项相当普通的任务,但是我在网络上找不到任何参考。我的文字带有标点符号,我想要一个单词列表。

"Hey, you - what are you doing here!?"

应该

['hey', 'you', 'what', 'are', 'you', 'doing', 'here']

但是Python str.split()只能使用一个参数,因此在用空格分割后,所有单词都带有标点符号。有任何想法吗?



6
蟒蛇的str.split()同时不带任何参数在所有工作
伊万·维诺格拉多夫

Answers:


468

正则表达式合理的情况:

import re
DATA = "Hey, you - what are you doing here!?"
print re.findall(r"[\w']+", DATA)
# Prints ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

2
谢谢。但是,仍然有兴趣-如何实现此模块中使用的算法?为何它不出现在字符串模块中?
ooboo

29
正则表达式起初可能令人生畏,但功能非常强大。正则表达式'\ w +'的意思是“一个单词字符(az等)重复一次或多次”。这里有关于Python正则表达式的HOWTO:amk.ca/python/howto/regex
RichieHindle

324
这不是问题的答案。这是一个不同问题的答案,恰好适用于此特定情况。好像有人问“我该如何左转”,而投票最多的答案是“接下来的三个右转”。它适用于某些交叉路口,但未给出所需的答案。具有讽刺意味的是,答案在其中re,但并非如此findall。下面给出的答案re.split()是优越的。
杰西·德隆

4
@JesseDhillon“采用由单词字符序列组成的所有子字符串”和“在由非单词字符序列组成的所有子字符串上分割”实际上只是表示同一操作的不同方式;我不确定为什么您会把这两个答案都叫优。
Mark Amery

4
@TMWP:撇号表示将like这样的单词don't视为一个单词,而不是将其拆分为donand t
RichieHindle

574

re.split()

re.split(pattern,string [,maxsplit = 0])

按模式分割字符串。如果在模式中使用了捕获括号,则模式中所有组的文本也将作为结果列表的一部分返回。如果maxsplit不为零,则最多会发生maxsplit分割,并将字符串的其余部分作为列表的最后一个元素返回。(不兼容说明:在原始的Python 1.5发行版中,maxsplit被忽略。此问题已在以后的发行版中修复。)

>>> re.split('\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split('(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split('\W+', 'Words, words, words.', 1)
['Words', 'words, words.']

13
此解决方案的优点是也可以轻松地在下划线上进行拆分,而findall解决方案则不具备以下优点:print re.split(“ \ W + | _”,“ Testing this_thing”)''yields:[[Testing','this' ,'thing']
EmilStenström'1

63
现在,如果我能记得的区别\w\W\s,和\S。谁认为旗帜的大写应该颠倒其含义,则需要从头脑中枪决。
ArtOfWarfare 2015年

1
字符串拆分的一个常见用例是从最终结果中删除空字符串条目。用这种方法可以做到吗?re.split('\ W +','abc')的结果为['','a','b','c','']
Scott Morken

3
@ArtOfWarfare通常使用shift键来做相反的事情。ctrl+z撤消与ctrl+shift+z重做。因此shift w,或W则与之相反w
弗兰克·维尔

1
这个答案应该放在最上面-这是唯一能准确回答问题标题的答案。
克拉纳赫

381

另一种无需使用正则表达式的快速方法是首先替换字符,如下所示:

>>> 'a;bcd,ef g'.replace(';',' ').replace(',',' ').split()
['a', 'bcd', 'ef', 'g']

71
快速又脏又适合我的情况(我的分离器是一小套,众所周知的)
Andy Baker

7
非常适合无法访问RE库的情况,例如某些小型微控制器。:-)
tu-Restate莫妮卡·多·杜(Monica-dor duh),2014年

11
我认为这也比RE更明确,因此有点菜鸟友好。有时并不需要为所有问题提供通用解决方案
Adam Hughes

太棒了 我在多个输入情况下有一个.split(),并且需要捕获用户(我)用空格而不是逗号分隔输入时的情况。我本来打算放弃并重铸re,但是您的.replace()解决方案触到了头。谢谢。
JayJay123

当您不想在空格上分割并且想要在其他字符上分割时,它将得到错误的答案。
艾哈迈德·阿姆

307

如此众多的答案,但我找不到有效解决问题标题真正要求的解决方案(拆分多个可能的分隔符,相反,许多答案拆分成一个单词而不是单词,这是不同的)。因此,这是标题中问题的答案,该问题依赖于Python的标准高效re模块:

>>> import re  # Will be splitting on: , <space> - ! ? :
>>> filter(None, re.split("[, \-!?:]+", "Hey, you - what are you doing here!?"))
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

哪里:

  • […]比赛一个隔板内上市,
  • \-在正则表达式是在这里以防止特殊解释-为字符范围指示器(如在A-Z),
  • +跳过一个或多个分隔符(它可以省略感谢filter(),但是这将不必要地产生匹配隔板之间空字符串),并
  • filter(None, …) 删除可能由前导和尾随分隔符创建的空字符串(因为空字符串具有错误的布尔值)。

re.split()正如问题标题所要求的那样,这恰好是“用多个分隔符分隔”。

此外,该解决方案还可以避免在其他一些解决方案中发现的单词中非ASCII字符的问题(请参见ghostdog74的答案的第一条评论)。

re模块比“手动”执行Python循环和测试要高效得多(在速度和简洁性方面)!


3
“我找不到有效解决问题标题真正要求的解决方案”-第二个答案做到了,发布于5年前:stackoverflow.com/a/1059601/2642204
BartoszKP 2014年

17
此答案不会在定界符处分割(从一组多个定界符开始):而是在任何不是字母数字的地方分割。就是说,我同意原始海报的目的可能只是保留文字,而不是删除一些标点符号。
Eric O Lebigot 2014年

停产:我认为这个答案确实在一组多个定界符上有所分歧。如果将非字母数字添加到未指定的字符串(如下划线),则不会按预期方式对它们进行拆分。
GravityWell 2014年

@GravityWell:我不确定我是否理解:您能举一个具体的例子吗?
Eric O Lebigot 2014年

3
@EOL:我只是意识到我对您的评论感到困惑,“这个答案没有分裂……”我以为“这个”指的是您重新拆分的答案,但是现在我意识到您是指gimel的回答。我认为这个答案(我正在评论的答案)是最好的答案:)
GravityWell 2014年

56

另一种方式,没有正则表达式

import string
punc = string.punctuation
thestring = "Hey, you - what are you doing here!?"
s = list(thestring)
''.join([o for o in s if not o in punc]).split()

8
该解决方案实际上比公认的解决方案好。它不支持ASCII字符,请尝试"Hey, you - what are you doing here María!?"。接受的解决方案不适用于前面的示例。
ChristopherRamírez2012年

4
我认为这里有个小问题...您的代码将附加以标点符号分隔的字符,因此不会将它们分割...如果我没记错,您的最后一行应为:''.join([o if not o in string.punctuation else ' ' for o in s]).split()
cedbeu 2013年

如有必要,可以使正则表达式库接受字符的Unicode约定。此外,这具有以前接受的解决方案所具有的相同问题:到目前为止,它在撇号上分开。您可能会想要o for o in s if (o in not string.punctuation or o == "'"),但是如果我们也添加cedbeu的补丁,那么对于单线而言,它变得太复杂了。
Daniel H

这里还有另一个问题。即使当我们考虑@cedbeu的更改时,如果字符串是类似的东西,"First Name,Last Name,Street Address,City,State,Zip Code"而我们只想用逗号分割,则此代码也不起作用,。所需的输出将是:['First Name', 'Last Name', 'Street Address', 'City', 'State', 'Zip Code']我们得到的是:['First', 'Name', 'Last', 'Name', 'Street', 'Address', 'City', 'State', 'Zip', 'Code']
Stefan van den Akker

4
这种解决方案效率极低:首先将列表解构成单个字符,然后对原始字符串中的每个单个字符进行完整的标点符号处理,然后将这些字符重新组合,然后再次拆分。与基于正则表达式的解决方案相比,所有这些“运动”也非常复杂:即使速度在给定的应用程序中无关紧要,也不需要复杂的解决方案。由于该re模块是标准模块,并且兼具可读性和速度,因此我不明白为什么应避免使用它。
Eric O Lebigot

39

专业提示:使用 string.translate用于Python最快的字符串操作。

一些证明...

首先,慢速的方式(对不起pprzemek):

>>> import timeit
>>> S = 'Hey, you - what are you doing here!?'
>>> def my_split(s, seps):
...     res = [s]
...     for sep in seps:
...         s, res = res, []
...         for seq in s:
...             res += seq.split(sep)
...     return res
... 
>>> timeit.Timer('my_split(S, punctuation)', 'from __main__ import S,my_split; from string import punctuation').timeit()
54.65477919578552

接下来,我们使用re.findall()(由建议的答案给出)。快多了:

>>> timeit.Timer('findall(r"\w+", S)', 'from __main__ import S; from re import findall').timeit()
4.194725036621094

最后,我们使用translate

>>> from string import translate,maketrans,punctuation 
>>> T = maketrans(punctuation, ' '*len(punctuation))
>>> timeit.Timer('translate(S, T).split()', 'from __main__ import S,T,translate').timeit()
1.2835021018981934

说明:

string.translate是用C实现的,与Python中的许多字符串操作函数不同,string.translate 它不会产生新的字符串。因此,它与字符串替换一样快。

不过,这有点尴尬,因为它需要翻译表才能执行此操作。您可以使用maketrans()便利功能制作翻译表。此处的目的是将所有不需要的字符转换为空格。一对一的替代品。同样,不会产生任何新数据。所以这很快

接下来,我们使用好old split()split()默认情况下,它将对所有空白字符起作用,将它们分组在一起以进行拆分。结果将是您想要的单词列表。而且这种方法的速度几乎快了4倍re.findall()


4
我在这里进行了测试,如果您需要使用unicode,则使用patt = re.compile(ur'\w+', re.UNICODE); patt.findall(S)它的速度要比转换更快,因为您必须在应用转换之前对字符串进行编码,并在拆分后对列表中的每个项目进行解码,以返回到unicode。
2013年

您可以单行转换实现,并确保S不在拆分器中,您可以:s.translate(''.join([(chr(i) if chr(i) not in seps else seps[0]) for i in range(256)])).split(seps[0])
滚刀

没有采取。您正在比较苹果和桔子。;)我在python 3中的解决方案仍然可以使用; P并支持多字符分隔符。:)尝试以简单的方式执行此操作,而不分配新的字符串。:)但没错,我的功能仅限于解析命令行参数,而不是一本书。
pprzemek

您说“不会产生新的字符串”,这意味着它可以在给定的字符串上正常工作?我现在使用python 2.7对其进行了测试,它不会修改原始字符串并返回新的字符串。
Prokop Hapala

26

我遇到了类似的难题,不想使用're'模块。

def my_split(s, seps):
    res = [s]
    for sep in seps:
        s, res = res, []
        for seq in s:
            res += seq.split(sep)
    return res

print my_split('1111  2222 3333;4444,5555;6666', [' ', ';', ','])
['1111', '', '2222', '3333', '4444', '5555', '6666']

1
我喜欢这个。请注意,分隔符的顺序很重要。抱歉,这很明显。
crizCraig 2011年

2
为什么不使用re既更快又更清晰的模块(不是正则表达式特别清晰,而是因为它更短更直接)?
Eric O Lebigot

13

首先,我想与其他人同意,正则表达式或str.translate(...)基于基础的解决方案性能最高。对于我的用例,此功能的性能并不重要,因此我想添加我考虑的该标准的想法。

我的主要目标是将其他一些答案中的想法归纳为一个解决方案,该解决方案可用于包含不仅仅是正则表达式单词的字符串(即,将标点字符的显式子集列入黑名单而将单词字符列入白名单)。

请注意,在任何方法中,都可能会考虑使用 string.punctuation代替手动定义的列表。

选项1-重新订阅

我很惊讶地发现到目前为止没有答案使用re.sub(...)。我发现这是解决此问题的一种简单自然的方法。

import re

my_str = "Hey, you - what are you doing here!?"

words = re.split(r'\s+', re.sub(r'[,\-!?]', ' ', my_str).strip())

在此解决方案中,我将调用嵌套到re.sub(...)内部re.split(...)-但如果性能至关重要,则在外部编译正则表达式可能会有所益处-对于我的用例而言,差异并不明显,因此我更喜欢简单性和可读性。

选项2-str.replace

这是另外几行,但是它具有可扩展的优点,而不必检查是否需要在正则表达式中转义某个字符。

my_str = "Hey, you - what are you doing here!?"

replacements = (',', '-', '!', '?')
for r in replacements:
    my_str = my_str.replace(r, ' ')

words = my_str.split()

能够将str.replace映射到字符串本来会很好,但是我不认为可以使用不可变的字符串来完成,并且在映射到字符列表时可以工作,对每个字符运行每个替换听起来太过分了。(编辑:有关功能示例,请参阅下一个选项。)

选项3-functools.reduce

(在Python 2中,reduce它可以在全局名称空间中使用,而无需从functools导入。)

import functools

my_str = "Hey, you - what are you doing here!?"

replacements = (',', '-', '!', '?')
my_str = functools.reduce(lambda s, sep: s.replace(sep, ' '), replacements, my_str)
words = my_str.split()

嗯,另一种方法是使用str.translate-它不具有Unicode功能,但很可能比其他方法要快,因此在某些情况下可能会很好:replacements=',-!?'; import string; my_str = my_str.translate(string.maketrans(replacements, ' ' * len(replacements)))在这里,也必须将替换项替换为字符串而不是元组或字符串。清单。
MarSoft

@MarSoft谢谢!我在答案的最前面提到了一个,但由于现有答案已经对其进行了很好的讨论,因此决定不添加它。
泰勒·埃德米斯顿

10
join = lambda x: sum(x,[])  # a.k.a. flatten1([[1],[2,3],[4]]) -> [1,2,3,4]
# ...alternatively...
join = lambda lists: [x for l in lists for x in l]

然后这变成了三层:

fragments = [text]
for token in tokens:
    fragments = join(f.split(token) for f in fragments)

说明

这就是在Haskell中被称为List monad的东西。monad背后的想法是,一旦“在monad中”,您就“停留在monad中”,直到有东西将您带出。例如在Haskell中,假设您将python range(n) -> [1,2,...,n]函数映射到List上。如果结果是一个列表,它将被原地追加到列表中,因此您将获得类似map(range, [3,4,1]) -> [0,1,2,0,1,2,3,0]。这称为map-append(或mappend,或类似的东西)。这里的想法是,您要执行此操作(拆分令牌),并且每当执行此操作时,您都将结果加入列表。

您可以将其抽象为一个函数,并且tokens=string.punctuation默认情况下具有。

这种方法的优点:

  • 这种方法(与基于朴素的基于正则表达式的方法不同)可以与任意长度的令牌一起使用(正则表达式也可以使用更高级的语法)。
  • 您不仅限于代币;您可以使用任意逻辑代替每个标记,例如,“标记”之一可以是根据嵌套括号的拆分方式进行拆分的函数。

整洁的Haskell解决方案,但是IMO可以在没有Mappend的情况下用Python更加清晰地编写。
弗拉德黑斑羚

@Goose:关键是可以使用2行函数map_then_append将问题变成2班轮,以及许多其他容易编写的问题。其他大多数解决方案都使用正则表达式re模块,该模块不是python。但是当我的答案非常简洁时,我对如何使我的答案显得不雅且过分感到不满意...我将对其进行编辑...
ninjagecko 2011年

这应该在编写的Python中工作吗?我的fragments结果只是字符串中的字符列表(包括标记)。
瑞克(Rick)支持莫妮卡(Monica)

@RickTeachey:它在python2和python3中都对我有效。
ninjagecko

嗯。也许这个例子有点模棱两可。我试图在回答代码各种不同ways-包括具有的fragments = ['the,string']fragments = 'the,string'或者fragments = list('the,string')和他们都不产生正确的输出。
里克

5

尝试这个:

import re

phrase = "Hey, you - what are you doing here!?"
matches = re.findall('\w+', phrase)
print matches

这将打印 ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']


4

两次使用替换:

a = '11223FROM33344INTO33222FROM3344'
a.replace('FROM', ',,,').replace('INTO', ',,,').split(',,,')

结果是:

['11223', '33344', '33222', '3344']

4

我喜欢re,但是这是我的解决方案:

from itertools import groupby
sep = ' ,-!?'
s = "Hey, you - what are you doing here!?"
print [''.join(g) for k, g in groupby(s, sep.__contains__) if not k]

sep .__ contains__是'in'运算符使用的方法。基本上和

lambda ch: ch in sep

但是这里比较方便。

groupby获取我们的字符串和函数。它使用该函数将字符串分成几组:每当函数值更改时,就会生成一个新的组。因此,sep .__ contains__正是我们需要的。

groupby返回一对对的序列,其中pair [0]是我们函数的结果,而pair [1]是一个组。使用'if not k'我们用分隔符过滤掉组(因为sep .__ contains__在分隔符上为True 的结果)。好了,就是这样-现在我们有了一系列的组,每个组都是一个单词(组实际上是一个可迭代的,因此我们使用join将其转换为字符串)。

该解决方案非常通用,因为它使用一个函数来分隔字符串(可以按需要的任何条件进行拆分)。另外,它不会创建中间字符串/列表(您可以删除联接,并且表达式将变得很懒,因为每个组都是迭代器)


4

您可以使用pandas的series.str.split方法来获得相同的结果,而不是使用re模块功能re.split。

首先,使用上面的字符串创建一个系列,然后将该方法应用于该系列。

thestring = pd.Series("Hey, you - what are you doing here!?") thestring.str.split(pat = ',|-')

参数pat接受定界符,并将拆分后的字符串作为数组返回。这里,两个定界符使用|传递。(或运算符)。输出如下:

[Hey, you , what are you doing here!?]


1
这不是冗长的问题,而是导入一个完整的库(我喜欢,顺便说一句),将一个字符串转换成熊猫系列后执行一个简单的任务。不太“ Occam友好”。
zar3bski

3

我正在重新熟悉Python,并需要同样的东西。findall解决方案可能更好,但是我想到了:

tokens = [x.strip() for x in data.split(',')]

聪明,应该适用于所有我能想到的英语语法结构,除了没有空格的破折号(例如)。(
可解决

3

使用maketrans和翻译,您可以轻松整齐地进行操作

import string
specials = ',.!?:;"()<>[]#$=-/'
trans = string.maketrans(specials, ' '*len(specials))
body = body.translate(trans)
words = body.strip().split()

关于Python> = 3.6的
revliscano

3

在Python 3中,您可以使用PY4E-Python for Everybody中的方法

我们可以通过使用字符串的方法解决这两个问题lowerpunctuationtranslate。该translate是最微妙的方法。这是有关以下内容的文档translate

your_string.translate(your_string.maketrans(fromstr, tostr, deletestr))

将中的字符替换为中fromstr相同位置的tostr字符,并删除中的所有字符deletestr。该fromstrtostr可以为空字符串和deletestr可以省略参数。

您可以看到“标点符号”:

In [10]: import string

In [11]: string.punctuation
Out[11]: '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'  

例如:

In [12]: your_str = "Hey, you - what are you doing here!?"

In [13]: line = your_str.translate(your_str.maketrans('', '', string.punctuation))

In [14]: line = line.lower()

In [15]: words = line.split()

In [16]: print(words)
['hey', 'you', 'what', 'are', 'you', 'doing', 'here']

有关更多信息,您可以参考:


2
字符串的translate()和maketrans()方法很有趣,但是此方法无法“在定界符处分割”(或空白):例如,“有很大的陷井”将错误地产生单词“ cavein”预期的“凹”和“中”…因此,这并不能满足问题的要求。
Eric O Lebigot

就像@EricLebigot评论的一样。上面的方法不能很好地解决问题所要求的。
Jeremy Anifacc '18

2

实现此目的的另一种方法是使用自然语言工具包(nltk)。

import nltk
data= "Hey, you - what are you doing here!?"
word_tokens = nltk.tokenize.regexp_tokenize(data, r'\w+')
print word_tokens

打印: ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

这种方法的最大缺点是您需要安装nltk软件包

好处是,一旦获得令牌,您就可以使用其余的nltk软件包做很多有趣的事情


1

首先,我不认为您的意图是在拆分函数中实际使用标点符号作为分隔符。您的描述表明您只是想从结果字符串中消除标点符号。

我经常遇到这种情况,而我通常的解决方案不需要重新输入。

具有列表理解功能的单行lambda函数:

(要求import string):

split_without_punc = lambda text : [word.strip(string.punctuation) for word in 
    text.split() if word.strip(string.punctuation) != '']

# Call function
split_without_punc("Hey, you -- what are you doing?!")
# returns ['Hey', 'you', 'what', 'are', 'you', 'doing']


功能(传统)

作为传统函数,这仍然只有两行具有列表理解功能(除了import string):

def split_without_punctuation2(text):

    # Split by whitespace
    words = text.split()

    # Strip punctuation from each word
    return [word.strip(ignore) for word in words if word.strip(ignore) != '']

split_without_punctuation2("Hey, you -- what are you doing?!")
# returns ['Hey', 'you', 'what', 'are', 'you', 'doing']

它自然也会使收缩和带连字符的单词保持完整。您总是可以text.replace("-", " ")在分割之前使用连字符将其转换为空格。

没有Lambda或列表理解的常规功能

对于更通用的解决方案(您可以在其中指定要消除的字符),并且无需列表理解,您将获得:

def split_without(text: str, ignore: str) -> list:

    # Split by whitespace
    split_string = text.split()

    # Strip any characters in the ignore string, and ignore empty strings
    words = []
    for word in split_string:
        word = word.strip(ignore)
        if word != '':
            words.append(word)

    return words

# Situation-specific call to general function
import string
final_text = split_without("Hey, you - what are you doing?!", string.punctuation)
# returns ['Hey', 'you', 'what', 'are', 'you', 'doing']

当然,您也可以始终将lambda函数概括为任何指定的字符串。


1

首先,在循环中执行任何RegEx操作之前,请始终使用re.compile(),因为它比常规操作更快。

因此对于您的问题,请先编译模式,然后对其执行操作。

import re
DATA = "Hey, you - what are you doing here!?"
reg_tok = re.compile("[\w']+")
print reg_tok.findall(DATA)

1

这是一些解释的答案。

st = "Hey, you - what are you doing here!?"

# replace all the non alpha-numeric with space and then join.
new_string = ''.join([x.replace(x, ' ') if not x.isalnum() else x for x in st])
# output of new_string
'Hey  you  what are you doing here  '

# str.split() will remove all the empty string if separator is not provided
new_list = new_string.split()

# output of new_list
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

# we can join it to get a complete string without any non alpha-numeric character
' '.join(new_list)
# output
'Hey you what are you doing'

或者一行,我们可以这样:

(''.join([x.replace(x, ' ') if not x.isalnum() else x for x in st])).split()

# output
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

更新的答案


1

创建一个函数,将两个字符串(要拆分的源字符串和定界符的splitlist字符串)作为输入,并输出一个拆分词列表:

def split_string(source, splitlist):
    output = []  # output list of cleaned words
    atsplit = True
    for char in source:
        if char in splitlist:
            atsplit = True
        else:
            if atsplit:
                output.append(char)  # append new word after split
                atsplit = False
            else: 
                output[-1] = output[-1] + char  # continue copying characters until next split
    return output

1

我喜欢pprzemek的解决方案,因为它不假定定界符是单个字符,并且不尝试利用正则表达式(如果分隔符的数目太长了,这将不能很好地工作)。

为了清楚起见,以下是上述解决方案的可读性更高的版本:

def split_string_on_multiple_separators(input_string, separators):
    buffer = [input_string]
    for sep in separators:
        strings = buffer
        buffer = []  # reset the buffer
        for s in strings:
            buffer = buffer + s.split(sep)

    return buffer

0

遇到了与@ooboo相同的问题,并找到了这个主题@ ghostdog74启发了我,也许有人觉得我的解决方案有用

str1='adj:sg:nom:m1.m2.m3:pos'
splitat=':.'
''.join([ s if s not in splitat else ' ' for s in str1]).split()

如果您不想在空格处分割,请在空格处输入内容并使用相同的字符分割。


如果我必须用字分割怎么办?
Harsha Biyani

0

这是我与多个决策者共同努力的结果:

def msplit( str, delims ):
  w = ''
  for z in str:
    if z not in delims:
        w += z
    else:
        if len(w) > 0 :
            yield w
        w = ''
  if len(w) > 0 :
    yield w

0

我认为以下是满足您需求的最佳答案:

\W+ 可能适合这种情况,但可能不适合其他情况。

filter(None, re.compile('[ |,|\-|!|?]').split( "Hey, you - what are you doing here!?")

我同意,\w\W解决方案不是问题(标题)的答案。请注意,在您的答案中,|应将其删除(您正在考虑使用expr0|expr1而不是[char0 char1…])。此外,不需要compile()正则表达式。
埃里克·O·勒比格

0

这是我的看法。

def split_string(source,splitlist):
    splits = frozenset(splitlist)
    l = []
    s1 = ""
    for c in source:
        if c in splits:
            if s1:
                l.append(s1)
                s1 = ""
        else:
            print s1
            s1 = s1 + c
    if s1:
        l.append(s1)
    return l

>>>out = split_string("First Name,Last Name,Street Address,City,State,Zip Code",",")
>>>print out
>>>['First Name', 'Last Name', 'Street Address', 'City', 'State', 'Zip Code']

0

我喜欢replace()最好的方式。以下过程将字符串中定义的所有分隔符更改splitlist为第一个分隔符splitlist,然后在该分隔符上拆分文本。它还说明是否splitlist碰巧是一个空字符串。它返回单词列表,其中没有空字符串。

def split_string(text, splitlist):
    for sep in splitlist:
        text = text.replace(sep, splitlist[0])
    return filter(None, text.split(splitlist[0])) if splitlist else [text]

0
def get_words(s):
    l = []
    w = ''
    for c in s.lower():
        if c in '-!?,. ':
            if w != '': 
                l.append(w)
            w = ''
        else:
            w = w + c
    if w != '': 
        l.append(w)
    return l

这是用法:

>>> s = "Hey, you - what are you doing here!?"
>>> print get_words(s)
['hey', 'you', 'what', 'are', 'you', 'doing', 'here']

0

如果要进行可逆操作(保留定界符),则可以使用以下功能:

def tokenizeSentence_Reversible(sentence):
    setOfDelimiters = ['.', ' ', ',', '*', ';', '!']
    listOfTokens = [sentence]

    for delimiter in setOfDelimiters:
        newListOfTokens = []
        for ind, token in enumerate(listOfTokens):
            ll = [([delimiter, w] if ind > 0 else [w]) for ind, w in enumerate(token.split(delimiter))]
            listOfTokens = [item for sublist in ll for item in sublist] # flattens.
            listOfTokens = filter(None, listOfTokens) # Removes empty tokens: ''
            newListOfTokens.extend(listOfTokens)

        listOfTokens = newListOfTokens

    return listOfTokens

0

我最近需要执行此操作,但需要一个与标准库str.split函数有些匹配的函数,当使用0或1个参数调用时,该函数的行为与标准库相同。

def split_many(string, *separators):
    if len(separators) == 0:
        return string.split()
    if len(separators) > 1:
        table = {
            ord(separator): ord(separator[0])
            for separator in separators
        }
        string = string.translate(table)
    return string.split(separators[0])

注意:仅当分隔符由单个字符组成时(如我的用例),此功能才有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.