天池Python训练营Day2 - 数据结构
Posted 文仙草
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了天池Python训练营Day2 - 数据结构相关的知识,希望对你有一定的参考价值。
数据结构
- 0. 数据结构
- 1. 列表 list
- 2. 元组tuple
- 3. 字符串 string
- 4. 字典 Dictionary
- 5. 集合 Set
0. 数据结构
数据结构指计算机中数据存储的方式。
0.1 序列(sequence)
序列(sequence) :python中最基本的一种数据结构,用于保存有序的数据。序列中所有的数据都有唯一的位置(索引),序列按照数据添加的顺序分配索引。
序列分为两大类:可变序列,不可变序列
- 可变序列:序列中的元素可以改变,包括:列表list、
- 不可变序列:序列中的元素不可以改变,包括:字符串str,元组tuple,
序列的通用操作:索引或切片查找、s.count(x)、 s.index(x)、len(s)、加号+拼接序列,乘号*重复序列、in/not in、min(s)、max(s)
序列的优点:存储数据性能好,存储整齐,便于批量取数。
序列的缺点:查询性能差,需要一个一个元素顺序查询。类似于看书没有目录,想要找到某一个章节,需要从第一页开始翻找。
0.2 映射(mapping)
映射:python中的一种数据结构。
映射的优点:查询性能好。类似于看书有了目录,可以直接找到所需的章节,而不需要从一页一页翻找。
0.3 常用数据结构总结
中文名 | 英文名 | 形式 | 是否有序 | 是否可索引 | 是否可修改元素(改值、排序、新增、删除等) |
---|---|---|---|---|---|
列表 | list | [元素1, 元素2] | 是 | 是 | 是(Mutable) |
元组 | tuple | (元素1, 元素2) | 是 | 是 | 否(Immutable) |
字典 | dictionary | key1:value, key2:value | 否 | 是(用key检索) | keys: 否(Immutable);values:是(Mutable) |
集合 | set | (元素1, 元素2) | 否 | 否 | 否(Immutable) |
1. 列表 list
列表:有序的序列,没有固定大小,能够保存任意数量、任意类型的对象。
- 列表的表示形式 list = [a,b,c,d]。其中,中括号[] 代表列表的范围,[]以内的都是这个列表的元素;逗号,将列表中每个元素分开。
- 也可以把列表看作用于存储对象的对象。
列表中的内容可更改 (mutable),可以增加 (append, extend)、插入 (insert)、删除 (remove, pop, del) 列表中的元素。
1.1 创建列表
- 用 [] 创建空列表
x = [] #创建空列表
- 枚举创建列表
x = [2, 3, 4, 5, 6, 7]
x = ['a', 1, [1,4], 3.14, print,True] #创建混合列表
print (x)
# 运行结果
# ['a', 1, [1, 4], 3.14, <built-in function print>, True]
- 用range创建列表
x = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
x = list(range(1, 11, 2)) # [ 1, 3, 5, 7, 9]
x = list(range(10, 1, -2)) # [ 10, 8, 6, 4, 2]
- 用循环函数创建列表
x = [0 for i in range(5)] # [0, 0, 0, 0, 0]
x = [i for i in range(5)] # [0, 1, 2, 3, 4]
x = [i for i in range(1, 10, 2)] # [1, 3, 5, 7, 9]
x = [i for i in range(10, 1, -2)] # [10, 8, 6, 4, 2]
x = [i ** 2 for i in range(1, 10)] # [1, 4, 9, 16, 25, 36, 49, 64, 81]
x = [i for i in range(40) if (i % 2) != 0 and (i % 3) == 0] # [3, 9, 15, 21, 27, 33, 39]
- 创建只包含0元素的列表
x = [0] * 4 # [0, 0, 0, 0, 0]
x = [[0]*3]*4 # [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
注意:由于列表的元素可以是任何对象,因此列表中保存的是对象的指针。例如,当创建一个列表[1,2,3]时,系统里实际上创建了3个指针和3个整数对象。
- x = [a] * 4操作中,创建了指向同一对象[a]的4个指针,所以一旦改变a,列表x中4个元素a都会改变。
x = [[0]*3]*4 # [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
x [0][0] = 1 #修改列表第一个元素里的第一个数值
print(x) # [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]] #列表所有元素的第一个数值都会被修改
1.1.1 列表方法method
列表方法:与具体的列表密切相关的函数。当调用列表方法时,需要先声明具体列表,调用语法为:列表名my_list.方法名method(x)
列表方法使用时,一般都会对列表中指定的元素obj或者位置index进行操作。因此,列表方法的调用与列表本身息息相关。
常用的列表方法:s.append(x), s.extend(x), s.insert(x), s.remove(x), s.pop(x), s.index(x), s.count(x)
- 对my_list.count(x)的中文理解:在变量名为my_list的列表中,计算值为x的元素的个数
- 对my_list.append(x)的中文理解:在变量名为my_list的列表末尾,增加一个值为x的元素
1.1.2 Nesting
列表中可以嵌套其他数据结构,比如列表中的元素可以是另一个列表、元组、字典等。嵌套的列表可以索引找到元素,比如:
- NL = [1,2,[2.1, 1, 2], ‘Dict’, [‘lily’,‘bob’], (‘name’, ‘sex’, (‘class’, ‘id’))]
- NL[4] 是 [‘lily’,‘bob’]
- NL[4][1] 是 ‘bob’
- NL[5][2][1] 是 ‘id’
1.2 新增列表元素
通过列表方法append()和extend()新增列表元素。注意,上述两个方法仅在列表的末尾增加元素。
-
append():(在列表末尾增加一个元素):
-
my_list.append(obj),在列表末尾添加新的对象,只接受一个参数obj。
-
该参数可以是任何数据类型,被追加的元素在 list 中保持着原结构类型。
-
extend():(扩展列表)
-
my_list.extend(seq) ,在列表末尾一次性追加另一个序列seq中的所有值。
-
用新列表扩展原列表。
#【示例】
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x.append(['Thursday', 'Sunday'])
#结果:['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', ['Thursday', 'Sunday']]
x.extend(['Thursday', 'Sunday'])
#结果: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Thursday', 'Sunday']
1.3 在列表中插入元素
insert():(在列表中间某个位置插入新元素)
my_list.insert(index, obj) :在编号 index 位置插入 对象obj。
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x.insert(2, 'Sunday')
#结果:['Monday', 'Tuesday', 'Sunday', 'Wednesday', 'Thursday', 'Friday']
1.4 删除列表元素
remove(obj), pop(index), del var1…,s[i:j] = []
- my_list.remove(obj) : 指定要删除的元素值obj,移除列表中该元素值的第一个匹配项。
#【示例 - remove()】
x = ['Monday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x.remove('Monday')
print (x) # ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
- my_list.pop(index): 指定要删除的位置index,移除列表中该指定位置index的元素(如不写index,则默认删除最后一个元素),删除后返回被删除元素的值。
#【示例 - pop()】
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
y = x.pop() # Friday
y = x.pop(0) # Monday
y = x.pop(-2) # Thursday 即删除倒数第2个
print(x) # ['Tuesday', 'Thursday']
- del var1[, var2 ……] :指定要删除的单个或多个对象。如果要同时删除多个元素且指定需删除元素在列表中的位置,可使用del语句。
#【示例 - del】
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
del x[0:2] #含头不含尾
print(x)
# 运行结果
# ['Wednesday', 'Thursday', 'Friday']
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
del x[::2] #切片删除,从第0个元素开始,每隔一个元素删除一个。
print (x)
# 运行结果
# ['Tuesday', 'Thursday']
- my_list[i:j]= []: 将列表s的某个位置的序列替换成空序列
#【用空序列替换原序列,删除原列表中的值】
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x[0:3] = [] #删除第0、1、2个元素
print (x)
# 运行结果
# ['Thursday', 'Friday']
备注:如果需要从列表中删除某元素,且不再以任何方式使用它,使用del;如果需要在删除元素后还能继续使用被删除的元素,使用pop()。
- 为什么remove()不返回被删除的值,而pop()返回被删除的值呢?remove()是删除指定的元素值,所以在使用remove的时候,程序员已经知道要被删除的值,再返回这个值没有意义。pop()是根据元素的位置进行删除,程序员可能不知道被删除位置的元素值,所以返回这个值有意义。
1.5 获取列表元素
1.5.1 索引index(获取单个元素)
索引 index:使用元素的index索引值,从列表获取单个元素。语法: my_list[index]
- 注意: 列表索引值是从0开始的。将索引指定为-1,可让Python返回最后一个列表元素,索引 -2 返回倒数第二个列表元素,以此类推。
#【示例-索引】
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x[0] #Monday
x[3] #Thursday
x[-1] #Friday
x[-2] #Thursday
1.5.2 切片 [起始:结束:步长] (获取多个元素)
切片:从现有列表中,获取一个子列表。切片后生成新的列表。切片不影响原列表。
- 语法: 列表名[起始位置:结束位置: 步长] 。切片获得的新列表包括起始位置的值,不包括结束位置的值。步长默认为1,可以设定。
#【列表切片】
names = ['Eva', 'Bob', 'Anna', 'Tom', 'John']
names [1:4] #['Bob', 'Anna', 'Tom']
- 切掉第一个和最后一个元素
names = ['Eva', 'Bob', 'Anna', 'Tom', 'John']
names [1:-1] #['Bob', 'Anna', 'Tom']
- 步长默认为1,可以设定。步长可以正数(代表从前向后)或者为负数(代表从后向前),但步长不可以为0。将步长设为-1,可得到倒叙的列表。步长为负数时,起始位置应大于结束位置,否则返回空列表
#【切片步长】
names [1:4:2] #['Bob', 'Tom']
names [1:5:3] #['Bob', 'John']
names [1:4:0] #ValueError: slice step cannot be zero 步长不可以为0
names [::-1] #['John', 'Tom', 'Anna', 'Bob', 'Eva'] 列表倒排
name [1:4:-1] #[] 步长为负数时,起始位置应大于结束位置,否则返回空列表
name [4:1:-1] #['John', 'Tom', 'Anna']
- 起始位置和结束位置均可以省略。如果省略起始位置,代表从第一个元素开始截取;如果省略结束位置,代表截取到最后一个元素;如果都省略,代表创建列表的一个副本。
#【省略起始位置】
new_1 = names[:3]
print (new_1) #['Eva', 'Bob', 'Anna']
#【省略结束位置】
new_2 = names[3:]
print (new_2) #['Tom', 'John']
#【省略起始位置和结束位置】
new_3 = names[:]
print (new_3) #['Eva', 'Bob', 'Anna', 'Tom', 'John']
1.6 其他通用操作
1.6.1 拼接和重复列表
- 加号+:将加号左右两侧列表拼接在一起
- 乘号*:将列表内的元素重复指定次数
#【列表拼接】
my_list = [1,2,3]+[4,5,6]
print (my_list)
# 运行结果
# [1,2,3,4,5,6]
#【列表重复】
my_list = [1,2,3] *3
print (my_list)
# 运行结果
# [1,2,3,1,2,3,1,2,3]
1.6.2 查找元素是否在列表内 in/not in
- in: 检查元素是否在列表内,在列表内返回True, 反之返回False
- not in: 检查元素是否不在列表内,不在列表内返回True, 反之返回False
# 【使用in和not in判读某元素是否在或不在列表内】
my_list = ['Eva',19,'Bob', 'Bonnie', 13]
i = 'Eva' in my_list
j = 'Eva' not in my_list
print (i, j)
# 运行结果
# True False
i = 21 in my_list
j = 21 not in my_list
# 运行结果
# False True
1.6.3 获取列表的长度 len()
- len(): 获取列表的长度,获取的是列表索引最大值+1
#【获取列表的长度】
list_1 = [1,'4',3,4,True]
len(list_1)
#输出
#[Out] 5
1.6.4 获取列表的最小值min 和最大值max
- min(): 获取最小值
- max(): 获取最大值
#【获取列表最大值和最小值】
my_list = [1,2,3,4,5,6]
max(my_list)
# 输出
# Out: 6
min(my_list)
# 输出
# Out: 1
1.6.5 获取列表中指定元素的个数 count()
- count(x): 用于获取列表中指定元素x的个数。注意,需要指定元素x,不指定元素会报错
- count()是一个方法(method), 需要通过一个具体的列表调用,可以理解为与对象联系紧密的函数,调用方法为list_name.count(x)
#【获取列表中元素个数】
my_list = [1,2,3,4,'Eva'*2, 'Anna', 'Hu', -0.13, 3, [3]*2, 3, 4]
my_list.count()
# 运行报错(因为没有指定元素)
# TypeError: count() takes exactly one argument (0 given)
print(my_list.count(2))
print(my_list.count(3))
print(my_list.count('Anna'))
# 运算结果
# 1
# 3
# 1
print(my_list.count([3]))
print(my_list.count([3]*2))
print(my_list.count([3,3]))
# 运算结果
# 0
# 1
# 1 因为[3]*2等于[3,3]
1.6.6 获取列表指定元素的位置 index()
- index(x): 获取列表中元素x第一次出现的位置index。如果列表中没有元素x,则抛出异常(ValueError)
- index()是一种方法,与count()一样,需要具体的列表才能调用,调用方法为list_name.index(x)。
- my_list.index(3): 即获取列表名称为’my_list’中值为3的元素第一次出现时的位置。
- 为什么index(x), count(x)调用时其前面都需要关联具体的列表,可以这么理解:上述两个函数都是针对列表内特定元素的操作,因此首先必须先找到这个特定的元素,而这个特定的元素一定是在某特定的列表里,所以上面两个函数依赖于特定的列表。在不同的列表查找同一个值,可能返回的结果不同。
#【获取指定元素的位置】
my_list = ['Bob','Anna', 3,21,4,3,'Bob', 3]
my_list.index(3) # 2
my_list.index('Bob') # 0
my_list.index('John') # ValueError: 'John' is not in list
- 进阶版 index(x, i, j): 返回从第i个位置开始到第j个位置(不包括第j个位置)结束之间,x第一次出现的位置。
- 可以有起始位置 i 但没有结束位置 j ,此时系统默认从起始位置 i 到列表最后一位;但是没有起始位置 i 但有结束位置 j ,此时,系统会报错。
#【获取指定元素的位置-进阶版】
my_list = ['Bob','Anna', 3,21,4,3,'Bob', 3]
my_list.index(3, 3)
#5 从列表index为3的元素开始向后查找值为3的元素,返回第一次出现位置的index
my_list.index(3, 6)
#7
my_list.index(3, 4, 7)
#5 在列表index为4的元素和index为7(不包括)的元素之间查找值为3的元素,返回第一次出现位置的index
my_list.index(3, 6, 7)
#ValueError: 3 is not in list 因为最后一个元素3的位置index为7,正好在查找的范围之外,所以不存在值为3的元素,系统报错
1.6.7 官方手册中的常用操作
可以从python官方手册中找到,步骤如下:
- 找到所使用的python版本的手册:Python 3.8.X(此处为版本号) Documents
- 在手册中,找到并点击 “The Python Standard Library” (或者官网上的链接"Library Reference")
- 找到第四部分 ”4 Built-in Types“
- 找到讲解序列的部分 “4.6 Sequence Types list, tuple, range”
- 点开序列部分,第一块内容就是常用操作 “4.6.1 Common Sequence Operations”
也可以点击此链接(3.8.8版本),一步到位
1.7 修改列表中的元素
1.7.1 直接通过索引修改
#【通过索引修改列表中的元素】
my_list = ['Bob','Anna', 3,21,4,3,'Bob', 3]
my_list[3] = 'John'
print (my_list)
# 运行结果
# ['Bob','Anna', 'John',21,4,3,'Bob',3]
1.7.2 通过切片修改
在使用切片修改列表时,必须传递一个序列。用切片等号右边的序列,替换切片等会左边列表里对应位置的序列
在不设置切片步长的情况下,替换的序列里的元素个数无需一一匹配。
#【通过切片修改列表】
my_list = ['Bob','Anna', 3,21,4,3,'Bob',3]
my_list[1:3] = ['John', 'Alan'] #用['John', 'Alan'] 替换原列表中位置为[1:3]的['Anna', 3]
print (my_list)
# 运行结果
# ['Bob', 'John', 'Alan', 21, 4, 3, 'Bob', 3]
my_list[1:3] = ['John', 'Alan', 'Max', 'Kate']
# 替换的序列中元素个数可以不等于原列表中的元素个数。
print (my_list)
# 运行结果
# ['Bob', 'John', 'Alan', 'Max', 'Kate', 21, 4, 3, 'Bob', 3]
my_list[1:3] = 123
# 运行报错,因为123不是序列。必须用序列替换序列
# TypeError: can only assign an iterable
- 当切片的起始位置和终止位置一致时,相当于在该位置插入等号右边的序列。由于等号左边为空序列,可以理解为,用等号右边的序列替换一个空序列。
my_list[1:1] = ['123']
print (my_list)
# 运行结果 在第0个元素和第1个元素位置中间插入’123‘,插入后,’123‘变成第1个元素。
# ['Bob', '123', 'John', 'Alan', 'Max', 'Kate', 21, 4, 3, 'Bob', 3]
my_list[5:5] = ['Helen', 'Julie']
# 运行结果
# ['Bob', '123', 'John', 'Alan', 'Max', 'Helen', 'Julie', 'Kate', 21, 4, 3, 'Bob', 3]
- 插入时,字符串中的每一个字母会被当作一个元素
#【在列表中切片插入字符串】
our_list = [1,2,3,4,5]
our_list[0:0] = '123'
print (our_list)
# 运行结果 字符串123中的每一个数字都会作为一个元素插入列表中
# ['1', '2', '3', 1, 2, 3, 4, 5]
在设置切片步长后,等式右边替换序列中元素的个数必须与等式左边切片中元素的个数一致
#【设置步长的切片修改】
our_list = [1,2,3,4,5,6]
our_list[::2] = [0]
# 运行报错 切片中元素个数为3,但是替换序列中元素个数为1,元素个数不足
# ValueError: attempt to assign sequence of size 1 to extended slice of size 3
our_list[::2] = [0]*3
print (our_list)
# 运行结果
# [0, 2, 0, 4, 0, 6]