我有多种语言的字符串,包括使用空格作为单词分隔符(英语,法语等)的语言和不使用空格的语言(中文,日语,韩语)。
鉴于这样的字符串,我想将英文/法文/等部分分成使用空格作为分隔符的单词,并将中文/日文/韩文部分分成单个字符。
我想将所有这些分开的组件放入列表中。
一些例子可能会说明这一点:
案例1 :仅英文字符串。这种情况很简单:
>>> "I love Python".split()
['I', 'love', 'Python']
案例2 :仅限中文字符串:
>>> list(u"我爱蟒蛇")
[u'\u6211', u'\u7231', u'\u87d2', u'\u86c7']
在这种情况下,我可以将字符串转换为中文字符列表。但是在列表中我得到了unicode表示:
[u'\u6211', u'\u7231', u'\u87d2', u'\u86c7']
如何让它显示实际字符而不是unicode?类似的东西:
['我', '爱', '蟒', '蛇']
...
案例3 :英语和英语的混合中国:
我想要输入一个输入字符串,例如
"我爱Python"
并将其转换为如下列表:
['我', '爱', 'Python']
是否可以做类似的事情?
答案 0 :(得分:6)
我以为我也会展示正则表达式方法。这对我来说感觉不对,但这主要是因为我所看到的所有语言特定的i18n奇怪让我担心正则表达式对于所有这些都不够灵活 - 但你可能根本不需要任何那个。 (换句话说 - 过度设计。)
# -*- coding: utf-8 -*-
import re
def group_words(s):
regex = []
# Match a whole word:
regex += [ur'\w+']
# Match a single CJK character:
regex += [ur'[\u4e00-\ufaff]']
# Match one of anything else, except for spaces:
regex += [ur'[^\s]']
regex = "|".join(regex)
r = re.compile(regex)
return r.findall(s)
if __name__ == "__main__":
print group_words(u"Testing English text")
print group_words(u"我爱蟒蛇")
print group_words(u"Testing English text我爱蟒蛇")
实际上,您可能只希望编译一次正则表达式,而不是每次调用。再次,填写字符分组的细节取决于你。
答案 1 :(得分:2)
格式化列表会显示其组件的repr
。如果您想自然地查看字符串而不是转义,您需要自己格式化。 (repr
应该不转义这些字符; repr(u'我')
应该返回"u'我'"
,而不是"u'\\u6211'
。显然,这确实发生在Python 3中;只有2 .x坚持使用以英文为中心的Unicode字符串转义。)
您可以使用的基本算法是为每个字符分配一个字符类,然后按类对字母进行分组。入门代码如下。
我没有使用doctest,因为我遇到了一些我不想研究的奇怪的编码问题(超出范围)。您需要实现正确的分组功能。
请注意,如果您将其用于自动换行,则还有其他每种语言注意事项。例如,你不想打破不间断的空间;你确实想打破连字符;对于日本人你不想分开きゅ;等等。
# -*- coding: utf-8 -*-
import itertools, unicodedata
def group_words(s):
# This is a closure for key(), encapsulated in an array to work around
# 2.x's lack of the nonlocal keyword.
sequence = [0x10000000]
def key(part):
val = ord(part)
if part.isspace():
return 0
# This is incorrect, but serves this example; finding a more
# accurate categorization of characters is up to the user.
asian = unicodedata.category(part) == "Lo"
if asian:
# Never group asian characters, by returning a unique value for each one.
sequence[0] += 1
return sequence[0]
return 2
result = []
for key, group in itertools.groupby(s, key):
# Discard groups of whitespace.
if key == 0:
continue
str = "".join(group)
result.append(str)
return result
if __name__ == "__main__":
print group_words(u"Testing English text")
print group_words(u"我爱蟒蛇")
print group_words(u"Testing English text我爱蟒蛇")
答案 2 :(得分:2)
在Python 3中,如果需要,它还会分割数字。
def spliteKeyWord(str):
regex = r"[\u4e00-\ufaff]|[0-9]+|[a-zA-Z]+\'*[a-z]*"
matches = re.findall(regex, str, re.UNICODE)
return matches
print(spliteKeyWord("Testing English text我爱Python123"))
=> ['测试','英语','文字','我','爱','Python','123']
答案 3 :(得分:0)
修改了Glenn的解决方案,删除符号并使用俄语,法语等字母表:
def rec_group_words():
regex = []
# Match a whole word:
regex += [r'[A-za-z0-9\xc0-\xff]+']
# Match a single CJK character:
regex += [r'[\u4e00-\ufaff]']
regex = "|".join(regex)
return re.compile(regex)
答案 4 :(得分:0)
以下内容适用于python3.7:
import re
def group_words(s):
return re.findall(u'[\u4e00-\u9fff]|[a-zA-Z0-9]+', s)
if __name__ == "__main__":
print(group_words(u"Testing English text"))
print(group_words(u"我爱蟒蛇"))
print(group_words(u"Testing English text我爱蟒蛇"))
['Testing', 'English', 'text']
['我', '爱', '蟒', '蛇']
['Testing', 'English', 'text', '我', '爱', '蟒', '蛇']
由于某种原因,我无法适应Glenn Maynard对python3的回答。