我想将巴西名字分成几部分。但是,有下面的名称"de"
,"da"
(和其他)不是单独的部分,它们总是使用下面的单词。所以正常的分裂并不起作用。
test1 = "Francisco da Sousa Rodrigues" #special split
test2 = "Emiliano Rodrigo Carrasco" #normal split
test3 = "Alberto de Francia" #special split
test4 = "Bruno Rezende" #normal split
我的预期输出是:
[Francisco, da Sousa, Rodrigues] #1
[Emiliano, Rodrigo, Carrasco] #2
[Alberto, de Francia] #3
[Bruno, Rezende] #4
对于特殊情况,我尝试了这种模式:
PATTERN = re.compile(r"\s(?=[da, de, do, dos, das])")
re.split(PATTERN, test1) (...)
但输出不是我的预期:
['Francisco', 'da Sousa Rodrigues'] #1
['Alberto', 'de Francia'] #3
知道怎么解决吗?有没有办法只使用一种模式" normal"和#34;特别"情况?
答案 0 :(得分:9)
名称是否总是以“规范”方式书写,即除了da,de,do之外,每个部分都是大写的......?
在这种情况下,你可以使用这个事实:
>>> import re
>>> for t in (test1, test2, test3, test4):
... print(re.findall(r"(?:[a-z]+ )?[A-Z]\w+", t, re.UNICODE))
['Francisco', 'da Sousa', 'Rodrigues']
['Emiliano', 'Rodrigo', 'Carrasco']
['Alberto', 'de Francia']
['Bruno', 'Rezende']
>>>
做你想做的事情的“正确”方式(除了根本不做),将是一个消极的看法:在没有任何da,de,do之前的空间上分开......可悲的是,这是(AFAIK)不可能的,因为re
要求lookbehinds具有相同的宽度。如果音节中没有名称 end ,您实际上无法假设,可以执行此操作:
PATTERN = re.compile(r"(?<! da| de| do|dos|das)\s")
您可能偶尔也可能不偶然发现不起作用的案件:如果第一个字母是重音字符(或文章,假设包含一个),则它将错误地匹配。要解决这个问题,你不会使用外部库; regex
您的新findall将如下所示:
regex.findall(r"(?:\p{Ll}+ )?\p{Lu}\w+", "Luiz Ângelo de Urzêda")
\p{Ll}
引用任何小写字母,\p{Lu}
引用任何大写字母。
答案 1 :(得分:2)
您可以在struct Student {
var id: Int = 0;
var name: String = String();
var course: String = String();
var GPA: Float = 0.0;
}
let student = [
Student(id: 201520032, name: "Ton Agnis", course: "BSITWMA", GPA: 3.69),
Student(id: 201620122, name: "Juan Cruz", course: "BSCSSE", GPA: 2.23),
Student(id: 201723214, name: "Pedro Sy", course: "BSITAGD", GPA: 2.87),
Student(id: 201418492, name: "Phot xPro", course: "BSCPE", GPA: 3.99)
]
func stud(get studs:[Student]){
print("Student No.\t\tID\t\tName\t\t\tCourse\t\tGPA")
for i in 0...studs.count - 1{
print("Student \(i+1) \t \(student[i].id)\t\(student[i].name)\t\t\(student[i].course)\t\t\(student[i].GPA)")
}
}
let x = student.sorted{ $0.GPA < $1.GPA }
stud(get: student)
print(x)
中将此正则表达式与可选组一起使用:
findall
此处我们在此可选项后面生成(?:(?:da|de|do|dos|das)\s+)?\S+
和1+空格。
代码示例:
(?:da|de|do|dos|das)
答案 2 :(得分:2)
使用python&#39; regex
库中的regex.split()
函数提供其他功能:
安装:
pip install regex
用法:
import regex as re
test_names = ["Francisco da Sousa Rodrigues", "Emiliano Rodrigo Carrasco",
"Alberto de Francia", "Bruno Rezende"]
for n in test_names:
print(re.split(r'(?<!das?|de|dos?)\s+', n))
输出:
['Francisco', 'da Sousa', 'Rodrigues']
['Emiliano', 'Rodrigo', 'Carrasco']
['Alberto', 'de Francia']
['Bruno', 'Rezende']
(?<!das?|de|dos?)\s+
- lookbehind否定断言(?<!...)
确保空格\s+
之前没有特殊情况之一da|das|de|do|dos
答案 3 :(得分:1)
在使用de_:
替换da和da_之后,可以逐步实现此操作lst = ["Francisco da Sousa Rodrigues" ,
"Emiliano Rodrigo Carrasco" ,
"Alberto de Francia" ,
"Bruno Rezende" ]
# replace da with da_ and de with de_
lst = list(map(lambda x: x.replace(" da ", " da_"), lst) )
lst = list(map(lambda x: x.replace(" de ", " de_"), lst) )
# now split names and then convert back _ to space:
lst = [ [k.replace("_", " ")
for k in l.split()]
for l in lst ]
print(lst)
输出:
[['Francisco', 'da Sousa', 'Rodrigues'],
['Emiliano', 'Rodrigo', 'Carrasco'],
['Alberto', 'de Francia'],
['Bruno', 'Rezende']]
编辑:回应评论,如果&#34; Fernanda Rezende&#34;类型名称在那里,然后可以用" da "
替换" da_"
(上面的代码从之前的"da "
更改为"da_"
)
还可以定义一个简单的函数来对列表的所有字符串进行更改,然后使用它:
def strlist_replace(slist, oristr, newstr):
return [ s.replace(oristr, newstr)
for s in slist ]
lst = strlist_replace(lst, " da ", " da_")
lst = strlist_replace(lst, " de ", " de_")
答案 4 :(得分:0)
这是因为您以特殊模式拆分字符串。这确实会将字符串分成两部分。
您可以尝试进一步分割第二部分,使用&#34; &#34;再次作为分隔符。请注意,如果有多个特殊分隔符实例,这不起作用。
另一种方法是使用&#34; &#34;作为分隔符,并使用以下名称连接每个特殊分隔符。例如:
[Francisco, da, Sousa, Rodrigues] # becomes...
[Francisco, da Sousa, Rodrigues]
答案 5 :(得分:0)
你可以尝试这样的事吗?
b_o_g=['da', 'de', 'do', 'dos', 'das']
test1 = "Francisco da Sousa Rodrigues"
test3= "Alberto de Francia"
def _custom_split (bag_of_words,string_t):
s_o_s = string_t.split()
for _,__ in enumerate(s_o_s):
if __ in bag_of_words:
try:
s_o_s[_]="{} {}".format(s_o_s[_],s_o_s[_+1])
del s_o_s [ _ + 1]
except IndexError:
pass
return s_o_s
print(_custom_split(b_o_g,test1))
print(_custom_split(b_o_g,test3))
输出:
['Francisco', 'da Sousa', 'Rodrigues']
['Alberto', 'de Francia']
答案 6 :(得分:0)
也许不是最好或最优雅的方式,但这会奏效。我还添加了test5以确定。
special_chars = ['da', 'de', 'do', 'dos', 'das']
test1 = "Francisco da Sousa Rodrigues" #special split
test2 = "Emiliano Rodrigo Carrasco" #normal split
test3 = "Alberto de Francia" #special split
test4 = "Bruno Rezende" #normal split
test5 = 'Francisco da Sousa de Rodrigues'
def cut(test):
t1 = test.split()
for i in range(len(t1)):
if t1[i] in special_chars:
t1[i+1] = t1[i] + ' ' + t1[i+1]
for i in t1:
if i in special_chars:
t1.remove(i)
print(t1)
cut(test1)
cut(test2)
cut(test3)
cut(test4)
cut(test5)
结果是:
['Francisco', 'da Sousa', 'Rodrigues']
['Emiliano', 'Rodrigo', 'Carrasco']
['Alberto', 'de Francia']
['Bruno', 'Rezende']
['Francisco', 'da Sousa', 'de Rodrigues']
答案 7 :(得分:0)
应该指出的是,我们在这里讨论的是标题,而不是名称。
这些几乎都转化为“来自”或“来自”之类的东西,而后通常指的是一个地方,它们起源于贵族头衔。
您正在尝试将非名称放入名称上下文中,这会使一切变得困难。
尝试删除所有这些,就像它不存在一样奇怪。就像你拿一个像“来自纽约的史蒂夫”之类的名字一样,只是试图放弃并使纽约成为“姓氏”。
这些从未打算成为姓氏,或者像大多数人的名字一样。随着时间的推移,事情只是朝着那个方向漂移,试图使圆钉适合方孔。
您可以在注册页面或其他位置添加标题字段,并将其指向用于标题的人作为更优雅的解决方案。
答案 8 :(得分:-2)
您的正则表达式应更改为
PATTERN = re.compile(r&#34; \ s(?= [da,de,do,dos,das])(\ S + \ s * \ s \ s * \ S +)&#34;)< / p>
import re
test1 = "Francisco da Sousa Rodrigues" #special split
test3 = "Alberto de Francia" #special split
PATTERN = re.compile(r"\s(?=[da, de, do, dos, das])(\S+\s*\s\s*\S+)")
print re.split(PATTERN, test1)
print re.split(PATTERN, test3)
这适用于我提供以下输出,
[&#39; Francisco&#39;,&#39; da Sousa&#39;,&#39; Rodrigues的&#39;] [&#39; Alberto&#39;,&#39; de Francia&#39;,&#39;&#39;]