Python 列表,元组与集合

1. 选择合适的数据结构

列表、元组、集合和字典是Python中最常用的复合数据结构,它们都属于容器类的数据结构。

(1) 列表

Python用数组的方式实现列表。列表的搜索时间是线性的,因此用列表来存储大量可搜索的数据是不切实际的。

(2) 元组

元组是不可变的列表,创建后就无法再更改。元组的搜索时间也是线性的。

(3) 集合

与列表和元组不同,集合不是序列:集合项不存在索引。集合最多只能存储一个项的副本,具有次线性O(log(N))的搜索时间。集合非常适合于成员查找和消除重复项。

在下面的例子中,展示了列表与集合查询速度对比,bigList是以十进制字符串表示的前1000万个整数的列表:

bigList = [str(i) for i in range(10000000)]
"abc" in bigList # 耗时0.2秒
bigSet = set(bigList)
"abc" in bigSet # 耗时15~30微秒——快了10 000倍!

(4) 字典

字典构建了从键到值的映射。任何可哈希的数据类型(数字、布尔、字符串、元组)的对象都可以作为键,且同一字典中的不同键可以属于不同的数据类型。Python对字典值的数据类型也没有限制。字典具有次线性O(log(N))搜索时间,它非常适合用于键值的查找。

你可以通过(键, 值)这样的元组列表创建字典,也可以使用内置类构造函数enumerate(seq)创建字典,这样得到的字典,其键为各项在seq中的序列号:

seq = ["alpha", "bravo", "charlie", "delta"]
d = dict(enumerate(seq))
print d # {0: 'alpha', 1: 'bravo', 2: 'charlie', 3: 'delta'}

另一种从键序列和值序列创建字典变量的巧妙方法,是使用内置类构造函数zip(kseq, vseq)(两个序列必须具有相同的长度):

kseq = ["apple", "bear", "banana"]
vseq = [12, 21, 3]
d = dict(zip(kseq, vseq))
print d # {'apple': 12, 'bear': 21, 'banana': 3}

Python将enumerate(seq)和zip(kseq, vseq)实现为列表生成器。列表生成器提供了一个迭代器接口,这使得我们可以在for循环中使用它们。与真正的列表不同的是,列表生成器只在需要时才生成下一个元素,这可以说是一种巧妙的偷懒方式。列表生成器便于处理大型列表,甚至允许“无限”的列表。你可以通过调用list()函数,将列表生成器显式强制转换为列表。

总结:

数据结构 查询时间复杂度 说明
列表 O(N) 数组实现,不适合大数据搜索
元组 O(N) 不可变的列表,不可更改,不适合大数据搜索
集合 O(log(N)) 不是序列,不存在重复项,适合成员查找
字典 O(log(N)) 键到值的映射,键和值数据类型无限制,适合键值查找

2. 列表推导式

列表推导式是一个将数据集(不一定是列表)转换为列表的表达式。通过列表推导式,可以实现对所有或某些列表元素应用相同的操作,例如将所有元素转换为大写或对其中大于0的元素进行运算等。

列表表达式的转换过程如下:

(1) 表达式遍历数据集并访问集合中的每一项。

(2) 为每一项计算布尔表达式(可选,不选默认为True)。

(3) 如果布尔表达式为True,则计算当前项目的循环表达式,并将其值附加到结果列表中。

(4) 如果布尔表达式为False,则跳过该项。

Example:

# 复制myList;等同于myList.copy()或者myList[:],但二者的效率都没有列表推导式高
[x for x in myList]
# 提取非负项
[x for x in myList if x >= 0]
# 用Mylist非零项的倒数构建一个新列表
[1/x for x in myList if x != 0]
# 从打开的infile文件中选出所有的非空行,并删除这些行开头和结尾的空格
[l.strip() for l in infile if l.strip()]

如果列表推导式被包含在圆括号中,而不是在方括号中,则程序将返回一个列表生成器对象:

(x**2 for x in myList) # 结果为:<generator object <genexpr> at 0x...>

3. 计数器

计数器是一种字典式集合,用于给集合项目计数。计数器定义在collections模块中。你可以将要计数的集合传递给构造函数Counter,然后使用函数most_common(n)来获取n个出现频率最高的项及对应频率的列表(如果没有提供参数n,则函数返回的将是一个针对所有项目的列表)。

phrase = "a boy eat a banana"
cntr = Counter(phrase.split())
print cntr.most_common() # [('a', 2), ('boy', 1), ('eat', 1), ('banana', 1)]

来源于:

您的支持将是我继续写作的动力!