List是python中一种很常见的数据结构,他有很多内置的函数或者操作,这些函数很有用,在这里从函数的功能(参数和输出),使用的场景,时间复杂度几个方面分析下这些函数。
Python的list的实现不是类似数据结构中的单链表,而是类似数组,也就是说==list中的元素保存在一片连续的内存区域中==,这样的话只有知道元素索引就能确定元素的内存位置,从而直接取出该位置上的值,但是它的缺点在于前插需要移动元素,而且随着list中元素的增多需要移动的元素也就越多,花费的时间也就自然多了。而单链表不同,单链表要得到某个位置上的元素必须要从头开始遍历,但是它的插入操作(前插或者后插)基本上都是恒定的时间,与链表中元素的多少没有关系,因为元素之间用“==指针==”维护着他们的关系。
参考的一个博客的博主,他的观点认为python中的列表其实是动态表,类似于C++中的vector和Java中的ArrayList。可以看算法导论中对动态表的介绍。
- 首先是list()函数,list()函数的作用是将字符转化成列表,举个例子:12345678>>> word = "Hello">>> name = list(word)>>> name['H', 'e', 'l', 'l', 'o']>>> mystr = "Welcome to here!">>> name = list(mystr)>>> name['W', 'e', 'l', 'c', 'o', 'm', 'e', ' ', 't', 'o', ' ', 'h', 'e', 'r', 'e', '!']
参数就是字符串,在使用list()函数以后,字符串里面的每一个字符都作为列表中的元素,第二个例子中,向空格和叹号这样的字符也被划分成一个列表中的元素。
- 接下来就是一些针对列表的操作:123456789101112131415161718192021222324252627282930313233343536>>> list = [1,'234','hello','!','']>>> list[1, '234', 'hello', '!', '']>>> list[0] = '3'>>> list['3', '234', 'hello', '!', '']>>> type(list[0])<class 'str'>>>> list[0] = 3>>> list[3, '234', 'hello', '!', '']>>> type(list[0])<class 'int'>>>> list[0] = 3.01>>> type(list[0])<class 'float'>>>> list[0] = [0,1,2]>>> list[[0, 1, 2], '234', 'hello', '!', '']>>> type(list[0])<class 'list'>>>> list[0] = {1:'hello', 2:'word'}>>> list[{1: 'hello', 2: 'word'}, '234', 'hello', '!', '']>>> type(list[0])<class 'dict'>>>> list[0] = (1,2,3)>>> list[(1, 2, 3), '234', 'hello', '!', '']>>> type(list[0])<class 'tuple'>>>> list[0] = True>>> list[True, '234', 'hello', '!', '']>>> type(list[0])<class 'bool'>
这么看来list虽然在一些方面和数组很像,但是他们两个的差别还是很大的,就比如上面的例子中list中的元素的类型可以是各种各样的,在创建一个list的时候不用考虑类型的问题,也不用考虑大小的问题(至于为什么不用考虑后面再继续研究下)。在上面的例子中还用到了python中的一个内置的函数type(),这个函数的作用就是查看对象的数据类型,要知道,在python中一切都是对象,所以type()是一个很实用的函数,并且type()本身也是有类型的,它是type类型的。
- 分片操作,类比数组就是取得子数组,但是python中的list的分片操作是很方便的。1234>>> listme = [1,2,3,4,5]>>> listme1 = listme[1:3]>>> listme1[2, 3]
在这里,通过标记索引来获得切片,比如这里的listme1 = listme[1:3],冒号左边是起始元素的索引,冒号右边是结束元素后面一个位置的索引,在例子中就是从listme[1]到listme[3-1],也就是listme[2],得到的切片包含两个元素,listme1 = [listme[1],listme[2]]。
在这里如果冒号左边的索引省略,则默认是从头开始;如果冒号右边的索引省略,则默认是一直到最后的元素。
修改序列:
1234>>> num = [0,1,2,3,4,5,6,7,8,9,10]>>> num[1:] = 'hello'>>> num[0, 'h', 'e', 'l', 'l', 'o']插入序列:
1234567891011>>> num[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]>>> num[2:2] = [1,2,3]>>> num[0, 1, 1, 2, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10]>>> mylist = ['he','hel','lo',1,2,3,'!','']>>> mylist['he', 'hel', 'lo', 1, 2, 3, '!', '']>>> mylist[3:3] = 'follow me'>>> mylist['he', 'hel', 'lo', 'f', 'o', 'l', 'l', 'o', 'w', ' ', 'm', 'e', 1, 2, 3, '!', '']
在插入的时候,如果插入的数据是列表或者字符串,那么列表的每项,字符串的每个字符都会作为列表的一个元素,而不是说列表或者字符串整体作为一个字符串插入。
那么问题来了,如果想作为整体插入该怎么办呢?
这时候要用到insert()函数,语法:list.insert(index, obj)。这个函数有两个参数第一个参数是要插入位置的索引,第二个参数是要插入的内容。
删除序列:把要删除的部分置为空列表即可
12345678>>> mylist['he', [2, 3, 4], 'hel', 'Follow me', 'lo', 1, 2, 3, '!', '']>>> mylist[2:] = []>>> mylist['he', [2, 3, 4]]>>> mylist[1:len(mylist)] = []>>> mylist['he']count()函数,用来统计某个元素在列表中出现的次数。
123>>> num = [1,2,3,3,4,5,6,7,5,4,6,7,8,3,0]>>> num.count(3)3len()函数用来统计列表中元素的个数,有时候也是用来计算列表的长度。
123>>> num = [1,2,3,3,4,5,6,7,5,4,6,7,8,3,0]>>> len(num)15append()函数用来在列表的最后一个位置插入元素(类似于入栈操作):
1234567>>> num = [1,2,3,3,4,5,6,7,5,4,6,7,8,3,0]>>> num.append(10)>>> num[1, 2, 3, 3, 4, 5, 6, 7, 5, 4, 6, 7, 8, 3, 0, 10]>>> num.append('hello')>>> num[1, 2, 3, 3, 4, 5, 6, 7, 5, 4, 6, 7, 8, 3, 0, 10, 'hello']
Tips:可以使用“+”来实现列表的相加操作:
- extend函数,修改原来的序列,链接两个序列产生新的序列:1234567>>> a = [1,2,3]>>> b = ['1','2','3']>>> a.extend(b)>>> a[1, 2, 3, '1', '2', '3']>>> b['1', '2', '3']
那么append()和extend()函数区别在哪里呢?个人认为一个是向列表的末尾逐个的插入新的元素,另一个是将另一个列表中的元素链接到前一个列表的后面。
- pop()函数,弹出指定的列表中的元素,如果不指定索引的话,默认是弹出列表的最后一个元素。pop()函数将元素弹出来之后,原来列表中就没有这个元素了,可以看成是一种删除列表中的元素的方法。123456789101112>>> a[1, 2, 3, '1', '2', '3']>>> b['1', '2', '3']>>> a.pop()'3'>>> a[1, 2, 3, '1', '2']>>> a.pop(0)1>>> a[2, 3, '1', '2']
其实pop()和append()搭档可以类比栈和队列,如果是appen()之后使用pop(),可以看成是先进后出,类比栈结构。但是append()之后写一个循环去pop(0)的话,就可以看成先进先出,可以模仿队结构。
remove()函数,就是删除遇到的第一个指定的元素,这是在知道元素的值得时候。
12345678910111213141516171819>>> num[1, 2, 3, 3, 4, 5, 6, 7, 5, 4, 6, 7, 8, 3, 0, 10, 'hello']# 因为只有一个1,所以删除了就没了>>> num.remove(1)>>> num[2, 3, 3, 4, 5, 6, 7, 5, 4, 6, 7, 8, 3, 0, 10, 'hello']# 但是3有多个,remove()函数就只是删除遇到的第一个符合条件的元素>>> num.remove(3)>>> num[2, 3, 4, 5, 6, 7, 5, 4, 6, 7, 8, 3, 0, 10, 'hello']# 那问题来了,如果一个元素在列表里面出现了很多次,怎样将他们全部删除呢?# 很简单啊,写个循环就好了,遇到这个元素就删掉,直到删光为止啊!>>> num[2, 3, 4, 5, 6, 7, 5, 4, 6, 7, 8, 3, 0, 10, 'hello']>>> while 3 in num:... num.remove(3)...>>> num[2, 4, 5, 6, 7, 5, 4, 6, 7, 8, 0, 10, 'hello']index()函数,用来寻找与某个指定元素匹配的第一个索引(匹配项的位置:
12345678>>> num[2, 4, 5, 6, 7, 5, 4, 6, 7, 8, 0, 10, 'hello']>>> num.index(4)1>>> num.index(33)Traceback (most recent call last):File "<stdin>", line 1, in <module>ValueError: 33 is not in listreverse()函数,可以翻转列表:
12345>>> num[2, 4, 5, 6, 7, 5, 4, 6, 7, 8, 0, 10, 'hello']>>> num.reverse()>>> num['hello', 10, 0, 8, 7, 6, 4, 5, 7, 6, 5, 4, 2]sort()函数,用来对列表中的元素进行排序。
12345678910111213>>> num['hello', 10, 0, 8, 7, 6, 4, 5, 7, 6, 5, 4, 2]>>> num.sort()Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: unorderable types: int() < str()>>> num.pop(0)'hello'>>> num[10, 0, 8, 7, 6, 4, 5, 7, 6, 5, 4, 2]>>> num.sort()>>> num[0, 2, 4, 4, 5, 5, 6, 6, 7, 7, 8, 10]
在这里,要排序的列表中的元素类型应该是一样的,
那么在这里排序是按照什么来进行的呢?这个可以参考一下大神们的博客:http://blog.csdn.net/zyl1042635242/article/details/43115675
sor()函数会修改原来的序列,如果采用b = a的方式,那么对b排序之后,a也改变了。
怎样做才能不会修改原来的列表呢?
两个方法,第一个方法就是使用sorted()函数:
另一种方法就是创建副本:
在这里如果b = a,那么a和b指向的就是同一个列表,如果b = a[:],那么b就是创建的一个a的副本,对b的操作不会影响到a。
关键字排序:key,举个例子一个元素都是字符串的列表中,按照字符串的长度来进行排序:
1234567891011>>> mystr['!', '1', 'Hello', 'follow me', 'last', 0]>>> mystr.sort(key = len)Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: object of type 'int' has no len()>>> mystr.pop()0>>> mystr.sort(key = len)>>> mystr['!', '1', 'last', 'Hello', 'follow me']关键词排序,reverse。因为sort()函数默认是按照从小到大排序的也就是升序排序,但是如果想按照从大到小排序也就是降序排序的话,需要指定关键字reverse,因为默认是False,所以要设置成True。
12345678910111213>>> mystr['!', '1', 'last', 'Hello', 'follow me']>>> mystr.sort(reverse = True)>>> mystr['last', 'follow me', 'Hello', '1', '!']>>> a[1, 4, 3, 1, 6, 7, 4, 8, 9, 2]>>> a.sort()>>> a[1, 1, 2, 3, 4, 4, 6, 7, 8, 9]>>> a.sort(reverse = True)>>> a[9, 8, 7, 6, 4, 4, 3, 2, 1, 1]cmp()函数,用来比较两个元素的大小。==但是python3.x中已经没有了cmp()函数,如果想要比较两个元素大小的话,需不要import进operator模块,==
123456789101112131415161718operator.lt(a, b)operator.le(a, b)operator.eq(a, b)operator.ne(a, b)operator.ge(a, b)operator.gt(a, b)operator.__lt__(a, b)operator.__le__(a, b)operator.__eq__(a, b)operator.__ne__(a, b)operator.__ge__(a, b)operator.__gt__(a, b)>>> import operator>>> operator.eq('hello', 'name');False>>> operator.eq('hello', 'hello');Trueset()函数,用来过滤掉列表中的重复的元素,也就是如果一个列表中有一个元素重复了很多次,使用set()函数之后只留下一个。
123456789101112131415>>> a[9, 8, 7, 6, 4, 4, 3, 2, 1, 1]>>> a.append(4)>>> a[9, 8, 7, 6, 4, 4, 3, 2, 1, 1, 4]>>> c = set(a)>>> c{1, 2, 3, 4, 6, 7, 8, 9}>>> c[2]Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: 'set' object does not support indexing>>> set([4,4,4,3,4,2,1,3,4,1,1,1,1,1,2]){1, 2, 3, 4}
set()完成之后,输出结果集合,集合中的元素是没有顺序的,所以再按照索引寻找元素就会出错。可以看得出来,每次转换成集合,里面的元素都是已经排好序的。
删除列表中的元素可以用del()
, pop()
, remove()
三种方法:
首先
del()
方法的参数是按照索引寻找的列表的元素,这种方法必须知道要删除的元素的索引。这个方法没有任何的返回值。12345>>> mylist['3', '6', '1', '3', '2', '1']>>> del mylist[0]>>> mylist['6', '1', '3', '2', '1']接下来
pop()
是将要删除的元素弹出来,并且删除该元素,这个方法也需要知道要删除的元素的索引,返回的是要删除的元素的值。123456>>> mylist['6', '1', '3', '2', '1']>>> mylist.pop(3)'2'>>> mylist['6', '1', '3', '1']最后是
remove()
这个是可以按照元素的值删除列表中的元素的。我们要先知道要删除的元素的值,将这个值作为参数传入到这个方法。看下面的代码可以知道,当列表中出现重复的元素的时候,也就是值相同的元素的时候,remove()
方法就删除掉从前往后第一个这个值的元素,也就是索引值最小的那个。而且remove()
是列表的一个属性方法,不能脱离列表单独使用。123456789>>> mylist['6', '1', '3', '1']>>> mylist.remove('1')>>> mylist['6', '3', '1']>>> remove(mylist[1])Traceback (most recent call last):File "<stdin>", line 1, in <module>NameError: name 'remove' is not defined未完待续