第六章 数据结构
6.1 数据结构
正如在现实世界中一样,直到我们拥有足够多的东西,才迫切需要一个储存东西的容器,这也是我坚持把数据结构放在后面的原因一一直到你掌握足够多的技能,可以创造更多的数据,你才会重视数据结构的作用。这些储存大量数据的容器,在 Python 称之为内置数据结构(Built-in Data Structure)。
我们日常使用的网站、移动应用,甚至是手机短信都依赖于数据结构来进行存储,其中的数据以一种特定的形式储存在数据结构中,在用户需要的时候被拿出来展现。
Python 有四种数据结构,分别是:列表、字典、元组,集合。
list = [val1, val2, val3, val4]
dict = {key1:val1, key2:val2}
tuple = (val1, val2, val3, val4)
set = {val1, val2, val3, val4}
从最容易识别的特征上来说,列表中的元素使用方括号扩起来,字典和集合是花括号,而元组则是圆括号。其中字典中的元素是均带有 ‘:’ 的 key 与 value 的对应关系组。
6.2 列表(list)
- 列表中的每一个元素都是可变的;
- 列表中的元素是有序的,也就是说每一个元素都有一个位置;
- 列表可以容纳 Python 中的任何对象。
想用没位置的值,跟字符串调用方法是一样的
Weekday = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
print(Weekday[0])
列表可以装入Python中的所有对象
all_in_list = [
1, #整数
1.0, #浮点数
'a word', #字符串
print(1), #函数
True, #布尔值
[1,2], #列表中套列表
(1,2), #元组
{'key':'value'} #字典
]
print(all_in_list)
试着打印这列表时发现,里边里面的函数会优先打印出来,然后才是列表的内容
列表的增删改查
插入元素
这里的1是插入元素的位置
fruit = ['pineapple', 'pear']
fruit.insert(1, 'grape')
print(fruit)
#['pineapple', 'grape', 'pear']
[0:0]对应的是位置0,[1:1]对应的是位置1,[0:1]会把第一个元素替换掉,这个得多尝试几次
fruit = ['pineapple', 'pear']
fruit.insert(1, 'grape')
fruit[0: 0] = ['orange']
print(fruit)
#['orange', 'pineapple', 'grape', 'pear']
删除列表中元素的方法是使用 remove():
fruit = ['pineapple', 'pear', 'grape']
fruit.remove('grape')
print(fruit)
替换修改其中的元素
fruit = ['pineapple', 'pear', 'grape']
fruit[0] = 'grapefruit'
print(fruit)
#['grapefruit', 'pear', 'grape']
另一种删除的方法,使用 del 关键字,[0:2]中括号里面可以是单个,也可以是挨着的几个,中括号里面数字还是包前不包后
fruit = ['pineapple', 'pear', 'grape']
del fruit[0: 2]
print(fruit)
#['grape']
索引和字符串是一样的
periodic_table = ['H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne']
print(periodic_table[0])
print(periodic_table[-2])
print(periodic_table[0:3])
print(periodic_table[-10:-7])
print(periodic_table[-10:])
print(periodic_table[:9])
#H
#F
#['H', 'He', 'Li']
#['H', 'He', 'Li']
#['H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne']
#['H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F']
6.3字典
- 字典中数据必须是以键值对的形式出现的;
- 逻辑上讲,键是不能重复的,而值可以重复;
- 字典中的键(key)是不可变的,也就是无法修改的;而值(value)是可变的,可修改的,可以是任何对象。
NASDAQ_code = {
'BIDU': 'Baidu',
'SINA': 'Sina',
'YOKU': 'Youku'
}
字典中的key不能重复,如果重复只能读取最后一个
a = {'key':123, 'key':321, 'key':1333}
print(a)
#{'key': 1333}
字典的增删改查
添加单一元素的时候,可以用这种方法,回家到字典的最后
NASDAQ_code = {'BIDU': 'Baidu', 'SINA': 'Sina'}
NASDAQ_code['YOKU'] = 'Youku'
print(NASDAQ_code)
#{'BIDU': 'Baidu', 'SINA': 'Sina', 'YOKU': 'Youku'}
字典中添加多个元素的方法 update(),也是添加到字典的最后
NASDAQ_code = {'BIDU': 'Baidu', 'SINA': 'Sina'}
NASDAQ_code['YOKU'] = 'Youku'
NASDAQ_code.update({'FB': 'Facebook', 'TSLA': 'Tesla'})
print(NASDAQ_code)
#{'BIDU': 'Baidu', 'SINA': 'Sina', 'YOKU': 'Youku', 'FB': 'Facebook', 'TSLA': 'Tesla'}
删除字典中的元素用del,中括号里面放的是字典的键这点很重要
NASDAQ_code = {'BIDU': 'Baidu', 'SINA': 'Sina'}
NASDAQ_code['YOKU'] = 'Youku'
NASDAQ_code.update({'FB': 'Facebook', 'TSLA': 'Tesla'})
del NASDAQ_code['FB']
print(NASDAQ_code)
#{'BIDU': 'Baidu', 'SINA': 'Sina', 'YOKU': 'Youku', 'TSLA': 'Tesla'}
6.4 元组
元组其实可以理解成一个稳固版的列表,因为元组是不可修改的,因此在列表中的存在的方法均不可以使用在元组上,但是元组是可以被查看索引的,方式就和列表一样:
letters = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
print(letters[0])
#a
6.5 集合
集合则更接近数学上集合的概念。每一个集合中的元素是无序的、不重复的任意对象,我们可以通过集合去判断数据的从属关系,有时还可以通过集合把数据结构中重复的元素减掉。
集合不能被切片也不能被索引,除了做集合运算之外,集合元素可以被添加还有删除:
a_set = {1,2,3,4}
a_set.add(5)
a_set.discard(5)
print(a_set)
#{1,2,3,4}
6.6 数据结构的一些技巧
多重循环
整理列表 sorted(),
- 按照长短、大小、英文字母的顺序给每个列表中的元素进行排序。
- sorted()函数并不会改变列表本身
- 使用默认参数 reverse 后列表可以被按照逆序整理
num_list = [6, 2, 7, 4, 1, 3, 5]
print(sorted(num_list))
print(num_list)
print(sorted(num_list,reverse=True))
#[1, 2, 3, 4, 5, 6, 7]
#[6, 2, 7, 4, 1, 3, 5]
#[7, 6, 5, 4, 3, 2, 1]
在整理列表的过程中,如果同时需要两个列表应该怎么办?这时候就可以用到 zip 函数
num_1 = [1, 2, 3, 4, 5]
num_2 = [1, 2, 3, 4, 5]
for a, b in zip(num_1, sorted(num_2, reverse=True)):
print(a, '×', b, '=', a * b)
#1 × 5 = 5
#2 × 4 = 8
#3 × 3 = 9
#4 × 2 = 8
#5 × 1 = 5
推导式(也叫列表解析式)
把10个元素装入列表,普通写法是这样的
a = []
for i in range(1, 11):
a.append(i)
推导式是这样写的
b = [i for i in range(1, 11)]
推导式比普通写法更简洁,更快速
这里说下书中的.clock已经在新版本中删掉了,我这儿用的是Python3.8,所以这里如果照着书上敲的话会报错,可以把。clock()替换成.perf_counter()
import time
a = []
t0 = time.perf_counter()
for i in range(1,20000):
a.append(i)
print(time.perf_counter() - t0)
t0 = time.perf_counter()
b = [i for i in range(1,20000)]
print(time.perf_counter() - t0)
#0.034554386000000006
#0.005016898999999991
推导式练习
a = [i ** 2 for i in range(1, 10)]
b = [j + 1 for j in range(1, 10)]
c = [n for n in range(1, 10) if n % 2 == 0]
d = [letter.lower() for letter in 'ABCDEFG']
print(a,'\n', b, '\n',c,'\n', d, sep='')
#[1, 4, 9, 16, 25, 36, 49, 64, 81]
#[2, 3, 4, 5, 6, 7, 8, 9, 10]
#[2, 4, 6, 8]
#['a', 'b', 'c', 'd', 'e', 'f', 'g']
字典的推导式这样写
a = {i: i + 1 for i in range(1, 4)}
print(a)
b = {i: j for i, j in zip(range(1, 4), 'abcde')}
print(b)
c = {i:j.upper() for i,j in zip (range(1,4),'abcde')}
print(c)
#{1: 2, 2: 3, 3: 4}
#{1: 'a', 2: 'b', 3: 'c'}
#{1: 'A', 2: 'B', 3: 'C'}
循环列表时获取元素的索引
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
for num,letter in enumerate(letters):
print(letter,'is',num + 1)
#a is 1
#b is 2
#c is 3
#d is 4
#e is 5
#f is 6
#g is 7
6.7 综合项目
做一个词频统计
需要先了解的知识点
- split()可以将字符串中每个单词分开
- count来统计重复出现的词
lyric = 'The night begin to shine, the night begin to shine.'
words = lyric.split()
print(words)
for word in words:
print(word, '-', words.count(word), end=', ', sep='')
#['The', 'night', 'begin', 'to', 'shine,', 'the', 'night', 'begin', 'to', 'shine.']
#The-1, night-2, begin-2, to-2, shine,-1, the-1, night-2, begin-2, to-2, shine.-1,
从上面代码运行返回的结果可以看出,代码还是有问题的,
- 有一些带标点符号的单词被单独统计了次数;
用strip(),括号里面的内容是要删除的内容,默认是空格。
再用import string里面有个标点符号,string.punctuation可以把所有的标点符号列出来(我们这里内容比较少,strip括号里面直接填‘,和.’就可以,但是遇到内容多的时候就不好用了) - 有些单词不止一次地展示了出现的次数;
这步可以用集合去重的特性过滤掉重复的词 - 由于 Python 对大小写敏感,开头大写的单词被单独统计了。
用lower()把词转换成统一小写的,对应的还有upper()小写转大写 - 用sorted()把字典拍下序
import string
lyric = 'The night begin to shine, the begin to shine. the'
words = [raw_word.strip(string.punctuation).lower() for raw_word in lyric.split()]
word_set = set(words)
word_dict = {word: words.count(word) for word in word_set}
for w in sorted(word_dict, key=lambda x: word_dict[x], reverse=True):
print(w, word_dict[w])
#the 3
#shine 2
#begin 2
#to 2
#night 1
网友评论