前言
最近一直在做leetcode和牛客网的题目,感觉是时候整理一波了。本文会时长更新,尽量将所用到的所有的关于列表、字符串、字典集合的常用基本操作覆盖在里面,方便以后查阅。希望读者在看本文的时候,重点浏览代码。笔者选用了一些最简单的例子,尽量做到一眼就能看懂。
列表 List
列表的创建
初始化一个空列表
a=[]
初始化一个长度为N,值为0的列表
N=7
a=[0]*N
print(a)
# output:
[0, 0, 0, 0, 0, 0, 0]
动态创建列表
为什么会有这个小标题呢?我们来先看个例子
a = []
for i in range(10):
a[i] = i
print(a)
#output
Traceback (most recent call last):
File "F:/pycharm/leetcode/dict1.py", line 3, in <module>
a[i] = i
IndexError: list assignment index out of range
假如定义一个空数组,则索引不能超过0。我们该如何解决这个问题呢?
假如事先知道列表长度:
a = [0]*10
for i in range(10):
a[i] = i
print(a)
#output
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
假如事先不知道列表长度:
a = []
for i in range(10):
a.append(i)
print(a)
#output
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
列表的索引
1 列表的索引从0开始。
a=[1,2,3,4,5]
print(a[1])
#output
2
2 取列表中的第3、4、5个元素
a=[1,2,3,4,5]
print(a[2:5])
#output
[3, 4, 5]
要注意的是,a[2:5]包括a[2] a[3] a[4]三个元素。记住一句诀窍就是包前不包后。
3 取列表的末尾三个元素
a=[1,2,3,4,5,6,7,8,9,10]
print(a[-4:-1])
#output
[8,9,10]
返回列表的索引
返回元素在列表中的位置,可以用index()函数。看下例子就会明白。
a = [1, 2, 3, 4, 5, 6]
print(a.index(4))
#output
3
值的说的一点是,index()函数对于二维列表同样有效。
a = [[1, 2], [3, 4], [5, 6]]
print(a.index([3, 4]))
#output
1
列表的添加
1 append
向列表末尾添加元素,如果添加的元素是列表,则原列表变为2维列表。若添加的元素是整数,则源列表形式不变。
2 extend
也是向列表末尾添加列表,源列表的形式。举例就会明白。
a=[1,2,3,4,5,6,7,8,9,10]
a.extend(10)
print(a)
#output
Traceback (most recent call last):
File "F:/pycharm/leetcode/str_leet.py", line 2, in <module>
a.extend(10)
TypeError: 'int' object is not iterable
a=[1,2,3,4,5,6,7,8,9,10]
a.extend([10,10])
print(a)
a.append([11,11])
print(a)
#output
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, [11, 11]]
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a.extend('b')
print(a)
a.append([11, 11])
print(a)
print(type(a[-1]), type(a[-2]), type(a[0]))
#output
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'b']
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'b', [11, 11]]
<class 'list'> <class 'str'> <class 'int'>
3 insert
insert()可实现在列表指定的位置处插入指定的值的元素。
a = [1, 2, 3, 4, 5]
a.insert(2, 30)
print(a)
#output
[1, 2, 30, 3, 4, 5]
列表的删除
1 del
a=[1,2,3,4,5]
del a[0]
print(a)
#output
[2, 3, 4, 5]
2 remove
a=[1,2,3,4,5]
a.remove(1)
print(a)
#output
[2, 3, 4, 5]
3 pop
这里需注意,pop()的参数的列表中元素的位置,若无参数则删除最后一个元素。
a=[1,2,3,4,5]
a.pop(1)
print(a)
a.pop()
print(a)
#output
[1, 3, 4, 5]
[1,3,4]
列表的排序
1 倒序排列
a=[1,2,3,4,5]
b=a[::-1]
print(b)
#output
[5, 4, 3, 2, 1]
2 二维数组的排序
a = [[5, 1], [4, 2], [3, 3], [2, 4], [1, 5]]
a.sort(key=lambda x: x[0])#按第一个元素排序
print(a)
a.sort(key=lambda x: x[1])#按第二个元素排序
print(a)
#output
[[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]
[[5, 1], [4, 2], [3, 3], [2, 4], [1, 5]]
3花样排序
a = [[5, 2], [5, 1], [1, 2], [2, 3], [3, 4], [4, 5]]
a.sort(key=lambda x: (-x[0])) # 按第一个元素排序
print(a)
#output
[[5, 2], [5, 1], [4, 5], [3, 4], [2, 3], [1, 2]]
上面的这个例子很好理解,按照第一个元素的降序进行排列。再看下面的例子。
a = [[5, 2], [5, 1], [1, 2], [2, 3], [3, 4], [4, 5]]
a.sort(key=lambda x: (-x[0],x[1])) # 按第一个元素排序
print(a)
#output
[[5, 1], [5, 2], [4, 5], [3, 4], [2, 3], [1, 2]]
注意这两个例子的区别在于,第二种方式是先根据第一个元素进行降序排列。然后当出现第一个元素值相同的情况时,再根据第二个元素进行升序排列。第一种方式中,出现第一个元素值情况相同时,默认排序情况是和源列表保持一致。
列表的备份
浅拷贝
加一个列表的备份的操作,原因的话,我们来看一个例子。
a = [[1, 2], [3, 4], [5, 6]]
b = a
a.append([7, 8])
print(a)
print(b)
#output
[[1, 2], [3, 4], [5, 6], [7, 8]]
[[1, 2], [3, 4], [5, 6], [7, 8]]
看到了吧。简单的b=a操作,并不能将列表备份起来。列表a进行一系列排序,增删操作之后,列表b同样会进行这些操作。出现这种情况的原因是因为python的设计问题。具体我就不多说了,直接上解决方案。
b=a[:]
我们再来看下效果。
a = [[1, 2], [3, 4], [5, 6]]
b = a[:]
a.append([7, 8])
print(a)
print(b)
#output
[[1, 2], [3, 4], [5, 6], [7, 8]]
[[1, 2], [3, 4], [5, 6]]
列表的统计
统计列表中元素的个数用count()函数。
a = [1, 2, 3, 4, 5, 6,1]
print(a.count(1))
#output
2
如果是二维列表,类似
a = [[1, 2], [3, 4], [5, 6], [3, 4]]
print(a.count([3,4]))
#output
2
列表的输出格式
a = [1, 2, 3, 4, 5, 6]
print(a)
#output
[1, 2, 3, 4, 5, 6]
现在问题来了,我如果要输出列表中的元素,且元素之间用空格分开,该如何操作。
a = [1, 2, 3, 4, 5, 6]
print('%d %d %d %d %d %d' % (a[0],a[1], a[2], a[3], a[4], a[5]))
#output
1 2 3 4 5 6
好,现在问题再进一步,假如有一个列表a,其中元素个数为N,N值很大,该如何以上述方式输出。
a = [1, 2, 3, 4, 5, 6]
N = len(a)
for i in range(N):
print(a[i], end=' ')
#output
1 2 3 4 5 6
除此之外,其实还有另一种方法。这里一并列出
a = [1, 2, 3, 4, 5, 6]
N = len(a)
print(' '.join(str(i) for i in a))
#output
1 2 3 4 5 6
二维列表的创建
1 生成一个m行n列,值为1的初始化列表
m, n = 3, 4
a = [[1] * n for _ in range(m)]
print(a)
#output
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
二维列表的切片
对于一个2维列表,如何取第一列或者第n列数据呢。
a = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
b = [i[0] for i in a]
print(b)
#output
[1, 5, 9]
去除列表中的重复元素
一维列表
一维列表去除重复元素非常简单。
a = [1, 2, 3, 4, 5, 2, 1]
b = list(set(a))
print(a)
print(b)
#output
[1, 2, 3, 4, 5, 2, 1]
[1, 2, 3, 4, 5]
二维列表
二维列表去除时稍微麻烦一些,不能使用一维列表的办法。
a = [[1, 2], [3, 4], [5, 6], [1, 2]]
b = list(set([tuple(t) for t in a]))
print(a)
print(b)
#output
[[1, 2], [3, 4], [5, 6], [1, 2]]
[(1, 2), (3, 4), (5, 6)]
二维列表的切片
取出二维列表的某行或某几行非常简单。
a = [[1, 2, 3], [4, 5, 6], [6, 7, 8]]
print(a[0:2])#取前两行元素
#output
[[1, 2, 3], [4, 5, 6]]
取出二维列表的某几列就稍微麻烦一些。我们需要用解析列表的方法读取某一列。
a = [[1, 2, 3], [4, 5, 6], [6, 7, 8]]
b = [x[0:2] for x in a]
print(b)
#output
[[1, 2], [4, 5], [6, 7]]
二维列表的求和
a = [[1, 2], [2, 3]]
print(sum(map(sum, a)))#一行代码搞定二维列表求和
#output
8
二维列表实现矩阵的相乘
矩阵A M行K列 矩阵B K行N列 相乘得到矩阵C M行N列
M, K, N = map(int, input().split())
a, b, c = [], [], []
for i in range(M):
a.append(list(map(int, input().split())))
for j in range(K):
b.append(list(map(int, input().split())))
for k1 in range(M):
c.append([])
for k2 in range(N):
s = sum(a[k1][k3] * b[k3][k2] for k3 in range(K))
c[k1].append(s)
for k in range(M):
print(c[k])
# 输入:
3 4 5
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
#输出
[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
字符串
字符串的创建
s1='abcde' #说明一下,在python中,单双引号几乎没有任何区别,我个人嫌麻烦,习惯单引号
s2=str(12345)
字符串的索引
字符串的访问和列表类似,也是从0开始。这里说下,python中所有的序列最开始的下标都是0,在C、C++中也是。在matlab中是从1开始的。
s = 'abcde'
print(s[0])
print(s[1:3])
print(s[-3: -1])
#output
a
bc
cd
字符串的连接
s1 = 'abcde'
s2 = '12345'
print(s1+s2)
print(s1+' '+s2)
#output
abcde12345
abcde 12345
字符串的比较
两个字符串之间是可以比较大小的。可以比较大小的原因在于每个字符都有其对应的ASCII码,我们比较两个字符串,是逐一比较对应字符的ASCII码大小。
s1 = 'abcde'
s2 = 'abcde'
print(s1==s2)
#output:
True
s1 = 'abcde'
s2 = 'abcda'
print(s1>s2)
#output:
True
s1 = 'abcde'
s2 = 'abcdf'
print(s1>s2)
#output:
False
这里说明一下,字符e的ASCII值是101,字符f的是102,因此,s1<s2。我们再来看一个例子。
s1 = 'abcde'
s2 = '12345'
print(s1 > s2)
#output:
True
字符串的内置函数
1 len(str)
返回一个字符串的长度
2 max(str) min(str)
返回字符串中对应ASCII值最大、最小的字符。
3 enumerate(str)、zip(str)
返回字符串的enumerate、zip型对象,以便在循环结构中使用。
s1 = 'abcde'
str1 = enumerate(s1)
for i, ele in str1:
print(i, ':', ele)
#output
0 : a
1 : b
2 : c
3 : d
4 : e
s1 = 'abcde'
str1 = zip(s1, '1234')
print(type(str1))
for i, ele in str1:
print(i, ':', ele)
#output
a : 1
b : 2
c : 3
d : 4
4 find()、index()
用于判断某字符是否存在于某个字符串中,若存在,则返回索引值,若不存在,则返回-1。
s1 = 'abcde'
ind1 = s1.find('a')
ind2 = s1.find('bc')
ind3 = s1.find('ac')
print(ind1, ind2, ind3)
#output
0 1 -1
s1 = 'abcde'
ind1 = s1.index('a')
ind2 = s1.index('bc')
ind3 = s1.index('abc')
print(ind1, ind2, ind3)
#output
0 1 0
从上面两个例子来看,find()函数和index()函数似乎没有区别?
没有区别那为何还要创造两个内置函数呢?所以肯定是有区别的。
s1 = 'abcde'
ind = s1.index('ac')
print(ind)
#output
Traceback (most recent call last):
File "F:/pycharm/SAIMA/test1.py", line 2, in <module>
ind = s1.index('ac')
ValueError: substring not found
没有返回-1,直接报错,是我找到的一个区别。其他的碰到再更新吧。
5 replace() 字符串的替换
s1 = 'abcde'
print(s1.replace('a','1'))
#output:
1bcde
这里需要注意一个问题,replace不会改变原字符串。什么意思呢,看个例子
s1 = 'abcde'
print(s1.replace('a','1'))
print(s1)
#output
1bcde
abcde
如果是这样的话,那么replace()函数的用途该是什么?这点我也很迷。
从字符串中取出数字
1
例:输入:‘abc123bba’ 输出:‘123’
import re
s=input()
s1=re.sub('\D','',s)
print(s1) #注意,s1为str类型数据
#output : 123
2
注意,牛客网和赛码网中不允许使用re模块,因此我们再总结一个不使用re模块的方法。
str = 'hongmao123lantu456'
s = ''.join([x for x in str if x.isdigit()])
print(s)
#output : 123456
从字符串中取出字母
1
例:输入:‘abc123bba’ 输出:‘abcbba’
import re
s = input()
s2 = ''.join(re.findall(r'[A-Za-z]', s))
print(s2)#注意,这里的s2仍为str类型
#output abcbba
2
str = 'hongmao123lantu456'
s = ''.join([x for x in str if x.isalpha()])
print(s)
#output:hongmaolantu
分割字符串
例: 输入: ‘r123c246’ 输出:一个列表[‘123’, ‘246’]
s = input()
s1 = s.strip('r')
s2 = s.split('c')
print(s1, type(s1))
print(s2, type(s2))
###########output#############
r123c246
123c246 <class 'str'>
['r123', '246'] <class 'list'>
统计字符串中子字符串的个数
这里推荐使用count()函数。不得不说,在python中,很多数据结构内容都被省去了。
a = 'abcgefdas'
b1 = 'a'
b2 = 'ab'
b3 = 'ad'
print(a.count(b1), a.count(b2), a.count(b3))
###########output#############
2 1 0
自行感受用法。这样至少省去了编程中的一个for循环操作。
字典
字典的初始化
dict1 = {'name': 'hongmao', 'age': 25}
print(dict1)
#output
{'name': 'hongmao', 'age': 25}
上面的是一种常规初始化方法,除此之外,我在网上还找到了另外一种初始化方法。
dict1 = dict((('name', 'hongmao'), ('age', 25)))
print(dict1)
#output
{'name': 'hongmao', 'age': 25}
使用这种方法的时候要注意那个括号问题,少一个都会报错。
字典的索引和长度
dict1 = {'name': 'hongmao', 'age': 25}
print(dict1['age'])
print(len(dict1))
#output
25
2
注意这里对字典进行索引时必须用中括号[]。
这里根据键获取对应的值还有另外一种方式。
dict1 = {'name': 'hongmao', 'age': 25}
data = dict1.get('name')
print(data)
#output
hongmao
取出字典中所有的值和健
dict1 = {'name': 'hongmao', 'age': 25}
key1 = dict1.keys()
value1 = dict1.values()
print(key1)
print(value1)
print(type(key1), type(value1))#看下我们得到的数据类型是什么
#output
dict_keys(['name', 'age'])
dict_values(['hongmao', 25])
<class 'dict_keys'> <class 'dict_values'>
现在有些人就懵逼了,得到了这些有啥用呢。我们自然是希望能够得到一个包含所有健和值的列表多好。别急,可以。不过我们需要稍微修改下代码。
dict1 = {'name': 'hongmao', 'age': 25}
key1 = list(dict1.keys())
value1 = list(dict1.values())
print(key1)
print(value1)
print(type(key1), type(value1))
#output
['name', 'age']
['hongmao', 25]
<class 'list'> <class 'list'>
这样,我们就得到了可以供我们直接使用的列表了。
复制字典
dict1 = {'name': 'hongmao', 'age': 25}
dict2 = dict1.copy()
dict1.clear()#将字典1清除
print(dict2)
#output
{'name': 'hongmao', 'age': 25}
这里为何要清除字典1,参考前面的 “列表的备份” 章节。
判断某个键是否在字典中
dict1 = {'name': 'hongmao', 'age': 25}
if 'name' in dict1:# 注意,这里只能判断键,不能判断值。如果把'name'改成'hongmao',则输出False
print(True)
else:
print(False)
#output
True
集合
在python中,set用来表示一个无序不重复元素的序列。在python中,set其实就是一个哈希表。主要作用可以用来给数据去重
集合的初始化
a = set()#专门用于创建一个空集合
print(type(a))
#output
<class 'set'>
a = {1, 2, 3, 'hongmao'}
print(a)
#output
{'hongmao', 1, 2, 3}
集合的索引
集合无法被索引,无法用()或[]来引用集合中的元素。
集合的添加
向集合中添加函数直接使用add()函数。
在这里插入代码片a = {1, 2, 3, 'hongmao'}
a.add('lantu')
print(a)
#output
{1, 2, 3, 'lantu', 'hongmao'}
向集合中添加已经存在的元素会有什么效果呢?不会报错,就像当做这个操作没发生一样。但是,我们可以判断是否能向集合中加入这个元素。这个性质十分有用。具体看例子。
a = {1, 2, 3, 'hongmao'}
if a.add('hongmao'):
print(1)
else:
print(0)
print(a)
#output
0
{1, 2, 3, 'hongmao'}
可以向集合中添加元组,但是不能添加列表
a = {1, 2, 3, 'hongmao'}
a.add((1, 2))
print(a)
#output
{(1, 2), 1, 2, 3, 'hongmao'}
集合的删除
1 remove
remove()函数用于删除指定的元素。
a = {1, 2, 3, 'hongmao'}
a.remove(2)
print(a)
#output
{1, 3, 'hongmao'}
2 pop
pop()函数随机在set中删除一个元素。和在列表中不一样,在列表中是删除最后一个元素。在集合中随机删除是因为集合的无序性。
a = {1, 2, 3, 'hongmao'}
a.pop()#在set中随机删除
print(a)
#output
{1, 3, 'hongmao'}
discard
discard()函数和remove()一样,删除指定的元素。两个函数相比,discard函数的优点在于,如果set中没有这个元素则会报错,而discard则不会。
a = {1, 2, 3, 'hongmao'}
a.remove('lantu')
print(a)
#output
Traceback (most recent call last):
File "F:/pycharm/leetcode/set1.py", line 2, in <module>
a.remove('lantu')
KeyError: 'lantu'
a = {1, 2, 3, 'hongmao'}
a.discard('lantu')
print(a)
a.discard(1)
print(a)
#output
{1, 2, 3, 'hongmao'}
{2, 3, 'hongmao'}
元组tuple
元组的特点是初始化后元素值不能再进行修改,元素之间使用逗号分隔开。