我想我想做的是一项相当常见的任务,但我在网上找不到任何参考资料。我有带标点符号的文本,我想要一个单词列表。
"Hey, you - what are you doing here!?"
应该是
['hey', 'you', 'what', 'are', 'you', 'doing', 'here']
但Python的str.split()只对一个参数有效,所以在用空格拆分后,所有单词都带有标点符号。有什么想法吗?
我想我想做的是一项相当常见的任务,但我在网上找不到任何参考资料。我有带标点符号的文本,我想要一个单词列表。
"Hey, you - what are you doing here!?"
应该是
['hey', 'you', 'what', 'are', 'you', 'doing', 'here']
但Python的str.split()只对一个参数有效,所以在用空格拆分后,所有单词都带有标点符号。有什么想法吗?
当前回答
我正在重新熟悉Python,需要同样的东西。findall解决方案可能更好,但我想到了这个:
tokens = [x.strip() for x in data.split(',')]
其他回答
遇到与@ooboo相同的问题并找到此主题@ghostdog74启发了我,也许有人觉得我的解决方案很有用
str1='adj:sg:nom:m1.m2.m3:pos'
splitat=':.'
''.join([ s if s not in splitat else ' ' for s in str1]).split()
在空格处输入内容,如果不想在空格处拆分,请使用相同的字符进行拆分。
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中所谓的列表monad。monad背后的想法是,一旦“进入monad”,你就“留在monad”直到有什么东西把你带走。例如,在Haskell中,假设您将python range(n)->[1,2,…,n]函数映射到List上。如果结果是一个List,它将被附加到List中,所以你会得到类似map(range,[3,4,1])->[0,1,2,0,1,2,3,0]的结果。这被称为map append(或mappend,或类似的东西)。这里的想法是,你已经得到了你正在应用的这个操作(对一个令牌进行拆分),每当你这样做时,你都会将结果加入到列表中。
您可以将其抽象为一个函数,并在默认情况下使用token=string.p标点符号。
这种方法的优点:
这种方法(与基于正则表达式的简单方法不同)可以使用任意长度的令牌(正则表达式也可以使用更高级的语法)。你不仅仅局限于象征;您可以使用任意逻辑来代替每个标记,例如,其中一个“标记”可以是一个函数,该函数根据括号的嵌套程度进行拆分。
我认为以下是满足您需求的最佳答案:
\W+可能适合这种情况,但可能不适合其他情况。
filter(None, re.compile('[ |,|\-|!|?]').split( "Hey, you - what are you doing here!?")
这是一个有一些解释的答案。
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']
更新的答案
首先,我不认为您的意图是在拆分函数中实际使用标点符号作为分隔符。您的描述表明您只是想从生成的字符串中删除标点符号。
我经常遇到这种情况,我通常的解决方案不需要re。
单行lambda函数,带列表理解:
(需要导入字符串):
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']
功能(传统)
作为传统函数,这仍然只有两行具有列表理解(除了导入字符串):
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函数推广到任何指定的字符串。