比如,我们想要把如下的字符串,拆分成不同的字段,该字符串包含多种不同的分割符,例如:
String_test = 'Xiao,Liang|shi,yi/ge;cheng|xu;yuan'
注意,split()函数的使用细节:
(1)split()
函数是一个字符串类函数,也就是说它只能处理字符串类型的数据;
(2)split()
函数一次只能处理字符串中一种类型的分割符,也就是说对于上述问题,要多次调用该函数;
(3)split()
函数的返回值是分割后的字符串的数组。
为了加深对split()
函数的理解,针对上面三条特性,分别进行验证。
split()
函数一次只能处理一种字符型分割符:split()
函数中直接输入字符串中的全部分割符,虽然程序没有报错,但是分割后的String_Split
字符串并没有进行分割操作。split()
函数的返回值为字符串数组:/
对字符串String_test
进行分割,得到的结果String_List_Split
为包含两个字符串的数组。split()
函数只能对字符串进行分割操作:split()
函数对字符串数组String_List_Split
进行分割操作,则会出现如下图所示的AttributError
报错信息。extend()
函数在列表末尾添加一个序列的多个值,它经常被用于扩展原列表的情况,其语法格式如下所示:
list.extend(seq)
seq
:元素列表;list
中以列表形式添加seq
的序列元素。通过下面例子来理解extend
函数:
lambda
匿名函数是没有名称的内联函数,其仅限于单个表达式,并可以使用在Python常规功能呢个的任何地方。
lambda
匿名函数是一个表达式,因此形式上简洁很多;lambda
匿名函数的主体是一个表达式,而不是一个代码块,因此仅仅在其表达式中封装有限的逻辑;lambda arg_1, arg_2, ..., arg_n: expression(arg_1, arg_2, ..., arg_n)
由上图可以看出,使用lambda
可以定义一个匿名的内联函数,该函数没有名称,上面的fun_sum
只是保存了已创建的lambda
函数的变量名称。
map
函数的作用可以理解为:其将一个集合中每一个元素映射为另一个集合,其调用格式如下所示,我们可以直观地理解为对data
中的每个元素迭代的使用iter_method
:
map(iter_method, data)
iter_method
:Python的可迭代方法,也可以是函数名字,也可以是匿名函数lambda
;data
:需要处理的数据。通过下面一个例子来理解map
函数:
假设我们从csv
文件中读取一段数字,并放到data列表中,通常情况下,我们读取的数据是以字符形式存放在data列表中的,比如:
data = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
但是,实际情况,我们用Python做数据处理时,想要得到的是数值型数据,这个时候我们就可以使用map
函数实现:
list(map(int, data))
由上图我们可以看出,map()
函数把int()
函数应用到data序列的每个元素,返回的列表是数值列表,而不是字符串列表。
注意:map()
函数的返回结果是可迭代对象,它能处理任何类型的迭代对象,Python中很多内置函数都可以应用于这样的映射-处理场景中,非常典型的就是在map()中使用匿名函数lambda。
本部分给出直观的编程和封装成函数的两种实现方式。
# 包含多种分割符的字符串
String_test = 'Xiao,Liang|shi,yi/ge;cheng|xu;yuan'
# 首先,使用split()函数以/分割符对String_test字符串进行分割
String_List_Split = String_test.split('/')
# 下面使用列表解析方法,对String_List_Split字符串列表进行切割
# 并以|分割符,对列表中每个字符串继续分割
String_List_Split = [string_item.split('|') for string_item
in String_List_Split]
# 注意,进一步分割后String_List_Split就变成了一个二维字符串数组,
# 对这个二维列表进行处理会很不方便。这里使用extend函数,将二维列表
# 转变为一维列表:
String_List_Split_Extend = [] # 开辟一个存储一维列表的内存空间
# 通过map函数和extend函数,并结合列表构造器list,将二维字符串数组
# String_List_Split转变为一维字符串数组,并存储于Sting_List_Split_Extend内。
list(map(String_List_Split_Extend.extend, String_List_Split))
# 此时,String_List_Split就变成一维数组了。
# 下面内容是作为扩展内容,感兴趣自行尝试,后续我还会专门介绍sum()函数的应用。
# 上面二维转一维略显地不好理解,我们还可以使用sum函数将二维字符串数组
# String_List_Split转变为一维,相较于上面的方法,该方法简洁很多。
# sum(String_List_Split, []) # 注意,默认sum函数加的初始值为0的整型数字,
# 而这里为数组,所以需要加上[]空列表参数。
下面为了便于更进一步理解上面的代码,逐行输出结果理解一下:
String_List_Split = String_test.split('/')
这条代码的输出结果如下图所示:
由上图我们可以看出,经过split
函数以/
分割副将字符串拆分成了字符串数组;如果进一步对String_List_Split列表进一步以|
分割符进行分割,注意这里使用列表解析的方法对列表中每个字符串进行了分割处理,代码如下所示:
String_List_Split = [string_item.split('|') for string_item
in String_List_Split]
处理结果如下图所示:
如上图所示,再次使用split
函数,进一步处理后的String_List_Split列表就变成了二维列表,非常不方便再做进一步的分割。
所以,才使用下面的指令将二维数组拉伸为一维的,并结合map
函数将这种拉伸操作映射到String_List_Split的每个元素。进而使用list
构造器构造列表,并将拉直的数组存放到String_List_Split_Extend内。代码如下所示:
String_List_Split_Extend = [] # 开辟一个存储一维列表的内存空间
list(map(String_List_Split_Extend.extend, String_List_Split))
由上图可以看出,经过上面代码的处理,String_List_Split_Extend存储的就是拉直的一维数组。进而重复上面的操作,直至最终分割完成。也可以将上面的代码放到针对分割符的一个for循环中就可以实现字符串的拆分了。
有了上面的理解,我们就可以进一步将上面包含多种分割符字符串拆分方法封装成函数形式,代码如下所示:
# 方法一:连续使用str.split()方法,但是该方法一次只能处理一种分割符。
# 因此,我们只能每次处理一种分割符号。
String_test = 'Xiao,Liang|shi,yi/ge;cheng|xu;yuan'
# 将上面的过程封装成一个函数String_Split
def String_Split(string, separators):
# 将传进来的列表放入统一的数组中
result_split = [string]
# 使用for循环每次处理一种分割符
for sep in separators:
# 使用map函数迭代result_split字符串数组
string_temp = [] # 用于暂时存储分割中间列表变量
list(
map(
lambda sub_string: string_temp.extend(sub_string.split(sep)),
result_split
)
)
# 经过上面的指令,中间变量string_temp就被分割后的内容填充了,
# 将分割后的内容赋值给result_split,并作为函数返回值即可
result_split = string_temp
return result_split
# 调用String_Split函数对字符串String_test进行分割
String_Split_Result = String_Split(String_test, ',|/;')
# 输出分割结果
print(String_Split_Result)
执行代码结果如下图所示:
理解本文代码的关键!
下面解释上面的代码是如何通过map()
和lambda
实现字符串拆分方法的,它是理解本文函数式代码的核心。
# result_split字符串列表是要分割的字符串
result_split = 'Xiao,Liang|shi,yi/ge;cheng|xu;yuan'
# 设置一个中间变量string_temp列表
string_temp = []
list(
map(
# lambda匿名函数定义了对自变量sub_string的分割函数,
# 即通过分割符sep分割result_split列表;并通过extend
# 函数实现了将二维数组拉伸为一维数组,以便对每个元素进行
# 迭代处理。
lambda sub_string: string_temp.extend(sub_string.split(sep)),
result_split
)
)