参考书目 | Python for Data Analysis, 2nd Edition |
---|---|
章节 | 第 3 章 Python数据结构、函数和文件 |
集合
集合的创建
集合中的元素是无序的、唯一的。集合可以通过花括号或者set
函数创建
In [12]: {1, 2, 2, 3, 3, 5, 7}
Out[12]: {1, 2, 3, 5, 7} # 集合中的元素是无序的,是唯一的
In [13]: set([1, 2, 2, 3, 5, 7])
Out[13]: {1, 2, 3, 5, 7}
集合的运算
集合的交集:可以使用union
方法,或者|
运算符
In [14]: a = {1, 2, 3, 4, 5}
In [15]: b = {3, 4, 5, 6, 7, 8}
In [16]: a.union(b)
Out[16]: {1, 2, 3, 4, 5, 6, 7, 8}
In [17]: a | b
Out[17]: {1, 2, 3, 4, 5, 6, 7, 8}
集合的并集:可以使用intersection
或者&
运算符
In [18]: a.intersection(b)
Out[18]: {3, 4, 5}
In [19]: a & b
Out[19]: {3, 4, 5}
常见的集合方法如下:
函数 | 替代语法 | 说明 |
---|---|---|
a.add(x) | N/A | 将元素x添加到集合a中 |
a.clear() | N/A | 清空集合中的元素 |
a.remove(x) | N/A | 将元素x从集合a中移除 |
a.pop() | N/A | 从集合a中去除任意元素,若集合为空,抛出KeyError异常 |
a.union(b) | a | b | 集合a与集合b的并集 |
a.update(b) | a |= b | 集合a中的元素为集合a和集合b的并集 |
a.intersection(b) | a & b | 集合a和集合b的交集 |
a.intersection_update(b) | a &= b | 设定集合a中的元素为集合a和集合b的交集 |
a.difference(b) | a - b | a集合与b集合的差 |
a.difference_update(b) | a -= b | 设定a集合为a集合与b集合的差 |
a.symmetric_difference(b) | a ^ b | 只在a集合或者只在b集合的元素 |
a.symmetric_difference_update(b) | a ^= b | 设定集合a中的元素为仅在a或者b集合中的元素 |
a.issubset(b) | N/A | 如果a集合是b集合的子集,则为True |
a.issuperset(b) | N/A | 如果b集合是a集合的子集,则为True |
a.isdisjoint(b) | N/A | 如果集合a与集合b无共同元素,则为True |
集合中的元素通常都是不可变的,要获得类似列表的元素,必须转换成元组
In [23]: my_data = [1, 2, 3, 4]
In [24]: my_set = {tuple(my_data)}
In [26]: my_set
Out[26]: {(1, 2, 3, 4)}
只有当两个集合的元素完全相同时,集合才相等
In [27]: {1, 2, 3} == {3, 1, 2}
Out[27]: True
列表、集合和字典推导式
列表推导式
列表推导式是Python最受欢迎的特性之一。它允许用户从一个集合过滤元素,形成列表,在传递参数的过程中还可以修改元素。形式如下:
[expr for val in collection if condition]
# 它等同于下面的for循环
result = []
for val in collection:
if condition:
result.append(expr)
举例说明,给定一个字符串列表,我们可以过滤出长度在2及以下的字符串,并将其转换为大写
In [28]: string = ['a', 'as', 'bat', 'car', 'dove', 'python']
In [30]: [x.upper() for x in string if len(x) <= 2]
Out[30]: ['A', 'AS']
字典推导式
字典推导式如下:
dict_comp = {key-expr: value-expr for value in collection if condition}
作为一个字典推导式的列子,创建一个字符串的查找映射,确定它在列表中的位置
In [34]: loc_mapping = {x : index for index, x in enumerate(string)}
In [35]: loc_mapping
Out[35]: {'a': 0, 'as': 1, 'bat': 2, 'car': 3, 'dove': 4, 'python': 5}
集合推导式
集合推导式如下:
set_comp = {expr for value in collection if condition}
与列表推导式类似,集合和字典推导式使得代码更加简洁。对于前面的字符串列表,如果想要获取字符串长度,用集合(元素是唯一的)推导式如下:
In [31]: unique_lengths = {len(x) for x in string}
In [32]: unique_lengths
Out[32]: {1, 2, 3, 4, 6}
使用map
函数可以进一步简化
In [33]: set(map(len, string))
Out[33]: {1, 2, 3, 4, 6}
# map函数可以根据提供的函数对指定的序列做映射
map(function, iterable, ...)
# function是对指定序列进行操作的函数
# iterable是一个或多个序列
# 返回值:python2 返回映射后的列表
# python3 返回一个可迭代序列
嵌套列表推导式
假设有一个包含列表的列表,里面有一些英文名和西班牙名
all_data = [['John', 'Emily', 'Michael', 'Mary', 'Steven'],
['Maria', 'Juan', 'Javier', 'Natalia', 'Pilar']]
现在我们想将名字中含有两个或者更多‘a’的放在一个列表中
In [3]: names_of_interest = []
In [4]: for names in all_data:
...: enough_es = [name for name in names if name.count('a') >= 2]
...: names_of_interest.extend(enough_es)
In [5]: names_of_interest
Out[5]: ['Maria', 'Natalia']
如果使用嵌套列表推导式,可以写成如下形式
In [7]: result = [name for names in all_data for name in names if name.count('a') >= 2]
In [8]: result
Out[8]: ['Maria', 'Natalia']
嵌套列表推导式有些复杂。推导式的for部分是根据嵌套的顺序由外到内书写,过滤条件还是放在最后。下面是另一个例子,将一个元组列表扁平化成一个整数列表
In [10]: some_tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
In [11]: flattened = [x for tup in some_tuples for x in tup]
In [12]: flattened
Out[12]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
原则上可以有任意多级别的嵌套,但是如果有两三个以上的嵌套,就要考虑代码的可读性问题了。同时注意分辨嵌套列表推导式与列表推导式中包含列表推导式的区别:
In [14]: [[x for x in tup] for tup in some_tuples]
Out[14]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
这段代码生成了一个包含列表元素的列表,而不是扁平化的只包含整数元素的列表。