# 5. 数据结构 3.7.0 3.8 3.7.0

## 5.1. 深入列表对象

List 数据类型包含更多的方法，下面是 List 对象包含的所有方法：

### `list.copy()`

``````>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.count('apple')
2
>>> fruits.count('tangerine')
0
>>> fruits.index('banana')
3
>>> fruits.index('banana', 4)  # 从索引 4 开始找 banana
6
>>> fruits.reverse()
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.append('grape')
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
>>> fruits.sort()
>>> fruits
['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
>>> fruits.pop()
'pear'
``````

### 5.1.1. 使用列表作为堆栈

``````>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]
``````

### 5.1.2. 使用列表作为队列

``````>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry")           # Terry 进入
>>> queue.append("Graham")          # Graham 进入
>>> queue.popleft()                 # 现在弹出第一个进入的元素
'Eric'
>>> queue.popleft()                 # 现在弹出第二个进入的元素
'John'
>>> queue                           # 按进入顺序维护队列
deque(['Michael', 'Terry', 'Graham'])
``````

### 5.1.3. 列表初始化表达式

``````>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
``````

``````squares = list(map(lambda x: x**2, range(10)))
``````

``````squares = [x**2 for x in range(10)]
``````

``````>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
``````

``````>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
``````

``````>>> vec = [-4, -2, 0, 2, 4]
>>> # 创建一个新列表，将原列表中的每个元素乘以 2
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # 去除原列表中的负数
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # 对原列表中的每个元素调用函数
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # 调用每个元素的成员方法
>>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> # 创建一个由二元组构成的列表，元素形如 (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # 元组必须以圆括号包含，否则将产生一个错误
>>> [x, x**2 for x in range(6)]
File "<stdin>", line 1, in <module>
[x, x**2 for x in range(6)]
^
SyntaxError: invalid syntax
>>> # 用一个含有两个 `for` 的列表初始化表达式将一个多维列表降维
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

``````>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
``````

### 5.1.4. 嵌套列表

``````>>> matrix = [
...     [1, 2, 3, 4],
...     [5, 6, 7, 8],
...     [9, 10, 11, 12],
... ]
``````

``````>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
``````

``````>>> transposed = []
>>> for i in range(4):
...     transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
``````

``````>>> transposed = []
>>> for i in range(4):
...     # 下面3行实现了嵌套列表的遍历
...     transposed_row = []
...     for row in matrix:
...         transposed_row.append(row[i])
...     transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
``````

``````>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
``````

## 5.2. `del` 语句

``````>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]
``````

`del` 也可用于删除整个变量：

``````>>> del a
``````

## 5.3. 元组和序列

``````>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # 元组也可以嵌套：
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # 元组不可被修改：
... t[0] = 88888
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # 但是可以包含可以被修改的对象：
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])
``````

``````>>> empty = ()
>>> singleton = 'hello',    # <-- 注意后面的逗号
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)
``````

``````>>> x, y, z = t
``````

## 5.4. 集合

Python 内建集合的数据类型。一个集合是由多个无重复元素构成的无序整体。集合支持的基本功能包括成员检查以及重复元素的去除。集合同时支持求并集、交集、差集以及对称差集等操作。

``````>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket                 # 快速成员检查
True
False

>>> # 由两个单词中独特的字母构成的集合进行的集合间操作
...
>>> b = set('alacazam')
>>> a                                  # a 集合中独特的字母
{'a', 'r', 'b', 'c', 'd'}
>>> a - b                              # 在 a 中但是不在 b 中的字母
{'r', 'd', 'b'}
>>> a | b                              # 在 a 中或在 b 中的字母
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b                              # a 和 b 共有的字母
{'a', 'c'}
>>> a ^ b                              # 在 a 中或在 b 中但两者不共有的字母
{'r', 'd', 'b', 'm', 'z', 'l'}
``````

Python支持类似于 递推式构造列表 的递推式构造集合：

``````>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}
``````

## 5.5. 字典

`list(d)` 操作会返回字典中所有键组成的列表，列表中的数据顺序按照这些键存入字典的顺序（如果想得到一个经过排序的键的列表，可以使用 `sorted(d)` ）。检查字典中是否有某个键，可以使用关键字  `in` 。

``````>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'jack': 4098, 'sape': 4139, 'guido': 4127}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'jack': 4098, 'guido': 4127, 'irv': 4127}
>>> list(tel)
['jack', 'guido', 'irv']
>>> sorted(tel)
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False
``````

`dict()` 函数会直接通过一系列的 键值对产生一个字典：

``````>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'guido': 4127, 'jack': 4098}
``````

``````>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
``````

``````>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'guido': 4127, 'jack': 4098}
``````

## 5.6. 遍历的技巧

``````>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
...     print(k, v)
...
robin the brave
``````

``````>>> for i, v in enumerate(['tic', 'tac', 'toe']):
...     print(i, v)
...
0 tic
1 tac
2 toe
``````

``````>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
...     print('What is your {0}?  It is {1}.'.format(q, a))
...
What is your name?  It is lancelot.
What is your quest?  It is the holy grail.
What is your favorite color?  It is blue.
``````

``````>>> for i in reversed(range(1, 10, 2)):
...     print(i)
...
9
7
5
3
1
``````

``````>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
...     print(f)
...
apple
banana
orange
pear
``````

``````>>> import math
>>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
>>> filtered_data = []
>>> for value in raw_data:
...     if not math.isnan(value):
...         filtered_data.append(value)
...
>>> filtered_data
[56.2, 51.7, 55.3, 52.5, 47.8]
``````

## 5.7. 判断条件进阶

``````>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim'
``````

## 5.8. 序列及其他类型的比较

``````(1, 2, 3)              < (1, 2, 4)
[1, 2, 3]              < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4)           < (1, 2, 4)
(1, 2)                 < (1, 2, -1)
(1, 2, 3)             == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab'))   < (1, 2, ('abc', 'a'), 4)
``````