【Python】数组
数组
数组基本概念
什么是数组(Array)
- 定义
- 数组是一种线性数据结构,存储一组相同类型的元素。
- 元素在内存中是连续存储的,因此可以通过**索引(index)**快速访问。
- 数组的本质是:一段连续的内存空间 + 一种统一的数据类型。
- 特点
- 有序:元素按照固定顺序排列,位置由索引决定。
- 索引访问:可以用下标访问任意元素,时间复杂度为 O(1)。
- 定长(传统意义上):在很多语言里,数组一旦创建大小固定(Python 的内置
list
比较特殊,它是动态数组)。 - 高效的随机访问:因为元素是连续存储的,定位第 i 个元素只需计算起始地址 + 偏移量。
数组 vs Python 内置容器
Python 本身没有像 C / Java 那样的原生固定数组,它主要有两种方式来使用数组概念:
- list(列表)
- Python 内置的
list
本质上是一个动态数组。 - 特点:
- 可以存放不同类型的元素(不像严格数组只能存相同类型)。
- 长度可变,支持自动扩容。
- 底层还是用连续的内存来存储元素的引用。
- Python 内置的
- array.array 模块
- Python 提供了一个
array
模块,定义了严格意义上的数组对象。 - 特点:
- 所有元素必须是相同的基本数据类型(例如全是整数、全是浮点数)。
- 底层存储更高效,适合数值计算。
- 用法类似于 C 语言数组。
- Python 提供了一个
- NumPy 的 ndarray
- 在科学计算和数据分析中,Python 主要用
numpy.ndarray
来代替普通数组。 - 特点:
- 强大的多维数组对象。
- 内存连续,支持向量化运算。
- 比 Python 原生
list
和array
更高效。
- 它是 Python 科学计算的基石。
- 在科学计算和数据分析中,Python 主要用
数组的组成部分
- 元素(Element)
- 数组中存储的数据项。
- 必须是相同类型(在严格数组中)。
- 索引(Index)
- 用来定位元素的位置。
- Python 的数组索引从 0 开始。
- 支持正向索引(0, 1, 2, …)和负向索引(-1 表示最后一个元素)。
- 容量(Capacity)
- 数组能够容纳的最大元素数量。
- 在动态数组(如 Python
list
)中,容量会动态变化。
- 长度(Length / Size)
- 数组当前实际存储的元素个数。
数组的分类
- 按维度分类
- 一维数组:线性结构,常见的数组形式。
- 例:
[1, 2, 3, 4]
- 例:
- 二维数组:数组的数组,可以看作表格 / 矩阵。
- 例:
[[1, 2], [3, 4], [5, 6]]
- 例:
- 多维数组:高维矩阵,用于科学计算、图像处理等。
- 例:三维数组可用于表示彩色图像(RGB)。
- 一维数组:线性结构,常见的数组形式。
- 按存储类型分类
- 静态数组:创建时大小固定(如 C 的数组)。
- 动态数组:大小可变(Python 的
list
就是动态数组)。
- 按数据类型分类
- 同质数组:所有元素必须是同一数据类型(
array.array
、numpy.ndarray
)。 - 异质数组:可以存储不同类型元素(Python
list
)。
- 同质数组:所有元素必须是同一数据类型(
数组的内存模型
-
存储方式
-
数组元素在内存中是连续存放的。
-
元素地址计算公式:
元素地址 = 起始地址 + (索引 × 元素大小)
-
这就是为什么数组可以在 O(1) 时间复杂度下访问任意位置的元素。
-
-
与链表对比
- 数组:适合快速随机访问,扩容或插入删除中间元素开销大。
- 链表:适合频繁插入删除,但随机访问效率低。
数组的常见应用场景
- 数据存储:存储一组相同类型的数据,如成绩表、图像像素点。
- 顺序访问:通过索引依次访问元素。
- 数学运算:向量、矩阵运算(特别是 NumPy 中)。
- 缓冲区:数组可用来做缓存或内存块(如字节数组
array('b')
)。 - 数据结构的基础:许多数据结构(如栈、队列、堆、哈希表)都基于数组实现。
创建数组
模块导入
-
Python 中严格数组来自内置模块
array
,需要先导入:import array
-
这是 Python 提供的 同质数组,即数组中所有元素必须类型相同(如全是整数、全是浮点数等)。
数组元素类型
array
模块要求在创建数组时指定类型码(typecode),用于定义数组中元素的类型和占用字节数。- 常见类型码:
类型码 | C 类型 | Python 类型 | 描述 |
---|---|---|---|
'b' | signed char | int | 1字节整数 |
'B' | unsigned char | int | 1字节非负整数 |
'h' | short | int | 2字节整数 |
'H' | unsigned short | int | 2字节非负整数 |
'i' | int | int | 4字节整数 |
'I' | unsigned int | int | 4字节非负整数 |
'l' | long | int | 4字节整数 |
'L' | unsigned long | int | 4字节非负整数 |
'q' | long long | int | 8字节整数 |
'Q' | unsigned long long | int | 8字节非负整数 |
'f' | float | float | 4字节浮点数 |
'd' | double | float | 8字节浮点数 |
类型码是数组创建时必须明确的,它保证了 数组同质性 和 内存高效。
数组的创建方式
array
模块的核心类是 array.array
,构造函数如下:
array.array(typecode, [initializer])
参数解析
typecode
:必需,元素类型码。initializer
:可选,初始元素序列(可以是列表、元组或其他可迭代对象)。
-
空数组创建
可以先创建一个空数组,再逐步填充:
import array arr = array.array('i') # 创建一个整数类型的空数组
特点:
- 内存高效,只分配类型所需空间。
- 长度为 0,后续可以用
append
或extend
添加元素。
-
通过可迭代对象初始化
直接用列表或元组初始化:
import array arr = array.array('i', [1, 2, 3, 4])
原理:
- Python 遍历
[1, 2, 3, 4]
,将每个元素按照'i'
类型编码到连续内存中。 - 内部会检查类型,如果列表中有非整数元素,会报错
TypeError
。
- Python 遍历
-
用生成器或其他可迭代对象
支持任意迭代器:
arr = array.array('f', (x * 0.5 for x in range(5)))
说明:
- 生成器表达式
(x*0.5 for x in range(5))
会逐步生成浮点数。 array
会按'f'
类型将元素转换为 4 字节浮点数存储。
- 生成器表达式
-
从已有数组复制
通过已有数组构造新数组:
arr1 = array.array('i', [1, 2, 3]) arr2 = array.array(arr1.typecode, arr1)
特点:
- 新数组与原数组类型相同。
- 内存重新分配,不共享底层内存。
数组创建中的内存和类型机制
- 内存连续性
array.array
底层使用 C 语言的数组实现。- 每个元素占据固定字节,连续存放,提高了访问效率和缓存友好性。
- 类型安全
- 创建数组时指定
typecode
后,数组只能存储该类型。 - 如果尝试存储不兼容类型,立即抛出
TypeError
,保证类型一致性。
- 创建数组时指定
- 动态扩容
- 虽然底层是连续内存,但 Python
array.array
可以动态扩容。 - 扩容策略与
list
类似:当容量不足时,申请更大连续空间,并复制原有数据。
- 虽然底层是连续内存,但 Python
创建数组时的注意事项
-
类型码必须合法
'x'
或其他不存在的类型码会报TypeError
。
-
初始化数据类型要匹配
-
例如:
array.array('i', [1, 2.5, 3])
会报错,因为
'i'
是整数类型,而 2.5 是浮点数。
-
-
大数组时建议用生成器
- 避免一次性创建大型列表,占用大量内存。
array.array('f', (i*0.1 for i in range(1000000)))
是高效的写法。
访问数组项
**访问数组项(Accessing array items)**指的是获取数组中某个特定位置存储的值的过程。
- 数组是一种容器,存储固定数量的相同类型元素。
- 每个元素的位置由**索引(Index)**标识,索引是一个整数。
- Python 使用
array
模块提供数组功能,保证数组中元素类型一致。
访问数组的核心就是通过索引或循环取出元素。
通过索引访问(Indexing)
索引访问是最直接的访问方式。
索引从 0 开始
- 第一个元素的索引为 0
- 最后一个元素的索引为
len(array)-1
语法:
array_name[index]
示例:
import array as arr# 创建整数数组
numericArray = arr.array('i', [111, 211, 311, 411, 511])# 索引访问
print(numericArray[0]) # 输出第1个元素
print(numericArray[1]) # 输出第2个元素
print(numericArray[2]) # 输出第3个元素
输出结果:
111
211
311
说明:索引可以直接定位到数组中的任意元素,访问时间复杂度为 O(1)。
通过迭代访问(Iteration)
当你需要依次访问数组中每一个元素时,可以使用循环。
for 循环:
for item in numericArray:print(item)
输出结果:
111
211
311
411
511
原理:
for item in array
会依次取出数组中的元素。- 适用于顺序处理数组的场景,如求和、统计等。
使用 enumerate()
访问
如果你不仅想要元素值,还想知道它的索引,可以用 Python 内置函数 enumerate()
。
语法:
enumerate(array, start=0)
array
:要遍历的数组start
:可选,起始索引(默认 0)
示例:
for idx, val in enumerate(numericArray):print(f"索引: {idx}, 值: {val}")
输出结果:
索引: 0, 值: 111
索引: 1, 值: 211
索引: 2, 值: 311
索引: 3, 值: 411
索引: 4, 值: 511
说明:enumerate
返回 (索引, 元素)
对,便于在循环中同时获取位置和元素。
访问数组范围(切片 Slicing)
有时我们需要访问数组的一段元素,这时可以用切片操作。
语法格式:
array[start:end:step]
start
:起始索引(包含该位置)end
:结束索引(不包含该位置)step
:步长,可选,默认 1
常用切片方式:
方式 | 含义 |
---|---|
[:index] | 从开头到指定索引(不包含 index) |
[index:] | 从指定索引到结尾 |
[:-index] | 从开头到倒数第 index 个元素 |
[start:end] | 从 start 到 end-1 的元素 |
[start:end:step] | 从 start 到 end-1,每隔 step 个元素取一次 |
示例:
# 创建数组
numericArray = arr.array('i', [111, 211, 311, 411, 511])# 从第3个元素到最后
print(numericArray[2:]) # 从第1个元素到第3个元素
print(numericArray[0:3])
输出结果:
array('i', [311, 411, 511])
array('i', [111, 211, 311])
说明:
- 切片操作返回一个新的数组对象,不修改原数组。
- 切片的灵活性让你可以快速获取数组的子集。
添加数组项
Python 数组可变性
- Python 的
array
是 可变序列(mutable sequence),意味着数组创建后可以修改和添加元素。 - 但是 数组中所有元素必须是相同类型,且只能将相同类型的数据添加到数组中。
模块支持
- Python 没有内置数组类型,使用
array
模块实现严格意义上的数组。 array
模块提供了多种方法来添加元素:append()
:在数组末尾添加单个元素insert()
:在指定位置插入元素extend()
:将另一个数组或可迭代对象的元素全部添加到当前数组
使用 append()
添加元素
作用
- 在数组末尾追加一个元素。
- 参数必须与数组类型相同。
语法:
array.append(value)
value
:要添加的元素
示例:
import array as arra = arr.array('i', [1, 2, 3])
a.append(10) # 在末尾添加元素10
print(a)
输出结果:
array('i', [1, 2, 3, 10])
说明:
append
每次只能添加一个元素。- 内部会在数组末尾分配空间并存储新值。
使用 insert()
在指定位置添加元素
作用
- 在数组中指定索引位置插入一个新元素。
- 其他元素会向后移动,保持顺序不变。
语法:
array.insert(index, value)
index
:插入位置索引value
:要插入的元素(必须与数组类型一致)
示例:
import array as arra = arr.array('i', [1, 2, 3])
a.insert(1, 20) # 在索引1的位置插入20
print(a)
输出结果:
array('i', [1, 20, 2, 3])
说明:
- 插入元素后,原索引及之后的元素会自动向后移动。
- 可以通过负数索引在数组末尾或倒数位置插入。
使用 extend()
添加多个元素
作用
- 将另一个数组或可迭代对象的所有元素添加到当前数组末尾。
- 用于 批量添加元素。
- 被添加的数组或可迭代对象必须与当前数组的类型相同。
语法:
array.extend(iterable)
iterable
:可迭代对象或数组
示例:
import array as arra = arr.array('i', [1, 2, 3, 4, 5])
b = arr.array('i', [6, 7, 8, 9, 10])a.extend(b) # 将数组b的元素全部添加到数组a末尾
print(a)
输出结果:
array('i', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
说明:
extend
可用于 连接两个数组。- 也可以接收 Python 列表或元组:
a.extend([11, 12, 13])
添加数组项的注意事项
- 类型一致性
- 不能向数组添加与数组类型不同的元素,否则会报
TypeError
:
- 不能向数组添加与数组类型不同的元素,否则会报
a.append(3.5) # 错误,如果数组类型是整数 'i'
-
性能考虑
-
append()
和insert()
只添加一个元素,insert()
会移动后续元素,开销较大 -
extend()
批量添加效率高于循环调用append()
-
-
数组是可变对象
- 添加元素会修改原数组,不会返回新数组。
删除数组项
Python 数组的可变性
- Python 的
array
是 可变序列(mutable sequence),意味着可以添加、修改、删除元素。 - 删除数组元素可以通过值或索引来实现。
模块支持
- Python 没有内置数组类型,使用
array
模块实现严格数组功能。 array
模块提供两种删除元素的方法:remove()
:根据值删除pop()
:根据索引位置删除
通过 remove()
删除元素(按值删除)
作用
- 删除数组中第一个匹配的元素值。
- 如果数组中不存在该值,会抛出
ValueError
。
语法:
array.remove(value)
value
:要删除的元素值
示例:
import array as arr# 创建数组
numericArray = arr.array('i', [111, 211, 311, 411, 511])print("删除前:", numericArray)# 删除元素值为311的项
numericArray.remove(311)print("删除后:", numericArray)
输出结果:
删除前: array('i', [111, 211, 311, 411, 511])
删除后: array('i', [111, 211, 411, 511])
说明:
remove()
只删除第一个匹配值- 如果数组有多个相同元素,需要循环调用
remove()
或使用其他方法批量删除。
通过 pop()
删除元素(按索引删除)
作用
- 根据索引位置删除元素,同时返回被删除的元素。
- 如果不传索引参数,默认删除最后一个元素。
语法:
array.pop(index)
index
:要删除元素的索引位置(可选,默认删除最后一个元素)
示例:
import array as arr# 创建数组
numericArray = arr.array('i', [111, 211, 311, 411, 511])print("删除前:", numericArray)# 删除索引为3的元素(第4个元素)
removed_element = numericArray.pop(3)print("删除后:", numericArray)
print("被删除的元素:", removed_element)
输出结果:
删除前: array('i', [111, 211, 311, 411, 511])
删除后: array('i', [111, 211, 311, 511])
被删除的元素: 411
说明:
pop()
可以删除任意位置的元素- 返回值是被删除的元素,便于进一步处理
- 当索引越界时会抛出
IndexError
删除数组项的注意事项
- 类型安全
- 数组类型决定了存储的数据类型,但删除操作不受类型限制,只删除匹配元素。
- 索引越界
- 使用
pop()
时,索引必须在[0, len(array)-1]
范围内,否则会报错。
- 使用
- 重复元素处理
remove()
只删除第一个匹配值- 若要删除所有重复值,需要循环或列表推导结合
remove()
- 删除操作的性能
remove()
:需要遍历数组查找值 → O(n)pop()
:删除末尾元素 O(1),删除中间元素 O(n)(因为需要移动后续元素)
循环数组项
循环作用
- 循环用于重复执行一段代码。
- 对数组进行循环,常见目的:
- 访问数组元素
- 修改数组元素
- 搜索或查找特定元素
- 聚合统计(求和、平均值等)
Python 中的循环类型
- for 循环:已知迭代次数时使用
- while 循环:迭代次数未知,直到满足条件停止
数组可迭代性
array
对象类似序列(sequence),可以像列表一样使用循环遍历元素。
使用 for
循环遍历数组(按元素迭代)
作用:当你只需要逐个访问数组元素时,用 for
循环最方便。
语法:
for element in array:# 处理 element
示例:
import array as arrnewArray = arr.array('i', [56, 42, 23, 85, 45])for item in newArray:print(item)
输出结果:
56
42
23
85
45
说明:
- 循环每次直接取出数组元素,无需关心索引。
- 适合只需要访问或处理元素的场景。
使用 while
循环遍历数组(按条件迭代)
作用
- 当循环条件不固定时,使用
while
循环。 - 需要手动维护循环变量(通常作为数组索引)。
语法:
index = 0
while index < len(array):# 处理 array[index]index += 1
示例:
import array as arra = arr.array('i', [96, 26, 56, 76, 46])
idx = 0
while idx < len(a):print(a[idx])idx += 1
输出结果:
96
26
56
76
46
说明:
- 循环条件为
idx < len(a)
- 每次访问数组元素后,需要手动增加索引
idx += 1
使用 for
循环结合索引遍历
作用
- 当你不仅需要元素值,还需要索引位置时,可以通过索引遍历数组。
步骤:
- 使用
len(array)
获取数组长度 - 用
range()
生成索引序列 - 使用索引访问元素
示例:
import array as arra = arr.array('d', [56, 42, 23, 85, 45])
length = len(a)for i in range(length):print(a[i])
输出结果:
56.0
42.0
23.0
85.0
45.0
说明:
for i in range(len(a))
可以同时获取索引和元素。- 适用于需要修改数组元素或使用索引进行计算的场景。
循环数组的应用场景
循环方式 | 适用场景 |
---|---|
for element in array | 仅访问元素值,无需索引 |
for i in range(len(array)) | 需要索引,或修改数组中的元素 |
while idx < len(array) | 迭代次数不确定,需要条件控制循环 |
复制数组项
复制数组的含义
- 复制数组就是创建一个新数组,使其包含原数组的所有元素。
- 复制数组可用于:
- 保留原数组不变,同时操作新数组
- 避免修改原数组造成数据干扰
Python 数组特点
- Python 的内置序列类型(列表 list、元组 tuple、字符串 str)是索引集合,元素可以是不同类型。
array
模块提供同质数组(元素类型一致),类似 Java 或 C/C++ 的数组。- 数组类型可以是整数、浮点数、字符串等。
数组构造示例:
import array# 创建一个整数类型数组
obj = array.array('i', [110, 220, 330, 440, 550])
'i'
表示整数类型(typecode)[110, 220, 330, 440, 550]
是初始化值
使用赋值操作复制数组(浅拷贝)
原理
- 使用赋值符号
=
直接把一个数组赋值给另一个变量。 - 注意:这并不是在内存中创建新数组,只是创建了 新的引用,指向同一个数组对象。
示例:
import array as arra = arr.array('i', [110, 220, 330, 440, 550])
b = a # 浅复制print("Copied array:", b)
print(id(a), id(b)) # 查看对象 id
输出结果:
Copied array: array('i', [110, 220, 330, 440, 550])
134485392383792 134485392383792
说明:
id(a)
和id(b)
相同 → 两个变量指向同一个数组- 如果修改其中一个,另一个也会被修改:
a[2] = 10
print(a, b)
输出:
array('i', [110, 220, 10, 440, 550]) array('i', [110, 220, 10, 440, 550])
使用深拷贝复制数组
原理
- 深复制会在内存中创建一个新的数组对象,并把原数组的元素全部复制到新数组中。
- 修改原数组不会影响新数组。
使用模块
copy
模块提供deepcopy()
函数实现深复制
示例:
import array as arr
import copya = arr.array('i', [110, 220, 330, 440, 550])
b = copy.deepcopy(a) # 深复制print("Copied array:", b)
print(id(a), id(b)) # id 不同,说明是新对象# 修改原数组
a[2] = 10
print(a, b)
输出结果:
Copied array: array('i', [110, 220, 330, 440, 550])
2771967069936 2771967068976
array('i', [110, 220, 10, 440, 550]) array('i', [110, 220, 330, 440, 550])
说明:
id(a)
和id(b)
不同 → 两个独立对象- 修改
a
不会影响b
复制方式 | 内存情况 | 修改原数组是否影响新数组 | 特点 |
---|---|---|---|
赋值 = | 指向同一个对象 | 会影响 | 快速,但不创建新数组,适合只读引用 |
深拷贝 copy.deepcopy() | 创建新数组对象 | 不影响 | 独立数组,修改原数组不会影响新数组 |
反向数组
反向数组的含义
- 反向数组指将数组中的元素顺序颠倒,即原来的第一个元素变为最后一个,最后一个变为第一个。
- 在数据处理中,反向操作常用于排序、倒序输出、栈模拟等场景。
Python 数组特点
- Python 自带序列类型(列表 list、元组 tuple)可以直接反向,但
array
模块提供同质数组(元素类型一致),类似 Java 或 C/C++ 的数组。
使用切片操作反向数组
原理
- Python 的切片操作可以提取数组的部分元素。
- 使用
[::-1]
表示从末尾到开头,以步长 -1 遍历。 - 切片会返回新数组,原数组保持不变。
语法:
reversed_array = original_array[::-1]
示例:
import array as arrnumericArray = arr.array('i', [88, 99, 77, 55, 66])
print("原数组:", numericArray)revArray = numericArray[::-1]
print("反向数组:", revArray)
输出结果:
原数组: array('i', [88, 99, 77, 55, 66])
反向数组: array('i', [66, 55, 77, 99, 88])
优点:
- 简洁快速
- 不改变原数组
使用 reverse()
方法(基于列表)
原理
reverse()
是列表对象的方法,不能直接作用于array
对象。- 解决方法:先用
tolist()
转为列表,调用reverse()
,再转回array
。
示例:
import array as arrnumericArray = arr.array('i', [10,5,15,4,6,20,9])
print("反转前数组:", numericArray)# 转为列表
listArray = numericArray.tolist()
# 反转列表
listArray.reverse()
# 转回数组
revArray = arr.array('i', listArray)
print("反转后数组:", revArray)
输出结果:
反转前数组: array('i', [10, 5, 15, 4, 6, 20, 9])
反转后数组: array('i', [9, 20, 6, 4, 15, 5, 10])
优点:
- 方法明确,语义清晰
- 原数组不改变
使用 reversed()
方法
原理
reversed()
函数接受序列,返回一个反向迭代器。- 可以通过
list()
转换为列表,再转换回数组。
示例:
import array as arrnumericArray = arr.array('i', [12, 10, 14, 16, 20, 18])
print("原数组:", numericArray)revArray = arr.array('i', list(reversed(numericArray)))
print("反向数组:", revArray)
输出结果:
原数组: array('i', [12, 10, 14, 16, 20, 18])
反向数组: array('i', [18, 20, 16, 14, 10, 12])
优点:
- 不需要切片
- 返回迭代器,可用于循环或构建新数组
使用 for
循环反向数组
原理
- 手动遍历原数组,从末尾到开头
- 将每个元素逐一添加到新数组
示例:
import array as arra = arr.array('i', [10,5,15,4,6,20,9])
b = arr.array('i', []) # 新数组for i in range(len(a)-1, -1, -1):b.append(a[i])print("原数组:", a)
print("反向数组:", b)
输出结果:
原数组: array('i', [10, 5, 15, 4, 6, 20, 9])
反向数组: array('i', [9, 20, 6, 4, 15, 5, 10])
优点:
- 可在循环中同时处理元素(例如修改或筛选)
- 灵活性高
反向数组总结
方法 | 原数组是否改变 | 返回类型 | 特点 |
---|---|---|---|
切片 [::-1] | 不改变 | 新数组 | 简洁快速,语义清晰 |
list().reverse() | 不改变 | 新数组 | 先转列表,方法明确 |
reversed() | 不改变 | 迭代器 → 新数组 | 可用于循环或转换,灵活 |
for 循环 | 不改变 | 新数组 | 手动遍历,适合在遍历中同时处理元素 |
排序数组
排序数组的含义
- 排序数组是指将数组中的元素按照**从小到大(升序)或从大到小(降序)**重新排列。
- 排序在数据处理、查找、统计等场景中非常常用。
Python 数组特点
- Python 的
array
模块提供同质数组,类似 Java 或 C/C++ 的数组,元素类型必须一致(整数、浮点数、字符等)。 array
模块本身没有内置的排序方法,但我们可以借助算法或 Python 内置函数实现排序。
使用排序算法(手写排序)
原理
- 可以使用经典排序算法(如冒泡排序、选择排序、插入排序)来实现数组排序。
- 以 冒泡排序 为例:
- 两层循环比较相邻元素
- 如果顺序不正确则交换
- 重复直到数组有序
示例(冒泡排序):
import array as arra = arr.array('i', [10, 5, 15, 4, 6, 20, 9])for i in range(len(a)):for j in range(i + 1, len(a)):if a[i] > a[j]:# 交换元素temp = a[i]a[i] = a[j]a[j] = tempprint(a)
输出结果:
array('i', [4, 5, 6, 9, 10, 15, 20])
优点:
- 可以完全自定义排序规则
- 不依赖 Python 内置函数
使用列表的 sort()
方法
原理
array
对象没有sort()
方法- 先用
tolist()
转为列表 - 调用列表的
sort()
方法进行排序 - 再转换回数组
示例:
import array as arrorgnlArray = arr.array('i', [10, 5, 15, 4, 6, 20, 9])
print("原数组:", orgnlArray)# 转换为列表
sortedList = orgnlArray.tolist()
# 列表排序
sortedList.sort()
# 转回数组
sortedArray = arr.array('i', sortedList)
print("排序后数组:", sortedArray)
输出结果:
原数组: array('i', [10, 5, 15, 4, 6, 20, 9])
排序后数组: array('i', [4, 5, 6, 9, 10, 15, 20])
优点:
- 直接利用 Python 内置的排序算法(TimSort)
- 语法简单
使用 sorted()
函数
原理
sorted()
是 Python 的内置函数- 可接受任意可迭代对象,返回新列表(升序排列)
- 可以通过
reverse=True
实现降序
语法:
sorted(iterable, reverse=False)
示例:
import array as arra = arr.array('i', [10, 5, 15, 4, 6, 20, 9])
# 使用 sorted 函数
sortedList = sorted(a) # 返回列表
sortedArray = arr.array('i', sortedList)
print("排序后数组:", sortedArray)
输出结果:
排序后数组: array('i', [4, 5, 6, 9, 10, 15, 20])
优点:
- 一步到位,不需要手动转换和循环
- 可直接对任意可迭代对象排序
三种方法对比总结
方法 | 是否改变原数组 | 返回类型 | 特点 |
---|---|---|---|
手写排序算法(冒泡排序) | 改变 | 原数组 | 灵活,可自定义排序规则,但代码较多 |
列表的 sort() 方法 | 可新建数组或修改原数组 | 新数组/原数组 | 简单快速,底层算法高效(TimSort) |
sorted() 内置函数 | 不改变原数组 | 新列表 → 可转数组 | 简单易用,可对任意可迭代对象排序 |
加入数组
数组合并的定义
- 合并两个数组就是把两个数组的元素连接在一起,形成一个新的数组。
- 在 Python 中,这种操作通常称为 Merging(合并) 或 Concatenation(连接)。
注意事项
- Python 的
array
是同质数组,元素类型必须相同(整型、浮点型或字符型)。 - 在合并前,务必保证两个数组的类型相同,否则会报错。
Python 支持的合并方式
- 使用
append()
方法 - 使用
+
运算符 - 使用
extend()
方法
使用 append()
方法
原理
append()
方法用于在数组末尾添加单个元素。- 要合并两个数组,可以通过循环,把第二个数组的每个元素依次
append
到第一个数组中。
示例:
import array as arr# 创建两个数组
a = arr.array('i', [10, 5, 15, 4, 6, 20, 9])
b = arr.array('i', [2, 7, 8, 11, 3, 10])# 通过 append 合并
for i in range(len(b)):a.append(b[i])print(a)
输出结果:
array('i', [10, 5, 15, 4, 6, 20, 9, 2, 7, 8, 11, 3, 10])
优点:
- 适合在循环中逐个添加元素
- 简单直观
缺点:对大数组效率较低,因为每次 append
都是一次操作
使用 +
运算符
原理
array
对象本身不支持直接+
运算- 解决方法:先转换为 列表(
tolist()
),用+
运算符连接两个列表,然后再转回数组
示例:
import array as arra = arr.array('i', [10, 5, 15, 4, 6, 20, 9])
b = arr.array('i', [2, 7, 8, 11, 3, 10])# 转为列表并合并
x = a.tolist()
y = b.tolist()
z = x + y# 转回数组
a = arr.array('i', z)
print(a)
输出结果:
array('i', [10, 5, 15, 4, 6, 20, 9, 2, 7, 8, 11, 3, 10])
优点:
- 代码简洁,一行即可完成合并
- 适合快速生成新的合并数组
使用 extend()
方法
原理
extend()
方法可以一次性将另一个数组或列表的所有元素添加到数组末尾- 与
append()
不同的是,append()
每次添加一个元素,而extend()
可以添加整个集合
示例:
import array as arra = arr.array('i', [88, 99, 77, 66, 44, 22])
b = arr.array('i', [12, 17, 18, 11, 13, 10])# 使用 extend 方法合并
a.extend(b)
print(a)
输出结果:
array('i', [88, 99, 77, 66, 44, 22, 12, 17, 18, 11, 13, 10])
优点:
- 高效,一次性合并整个数组
- 语法简单,推荐使用
三种方法对比
方法 | 是否修改原数组 | 操作对象 | 优点 | 缺点 |
---|---|---|---|---|
append() + 循环 | 修改原数组 | 单个元素 | 简单直观,适合逐个处理 | 大数组效率低 |
+ 运算符 | 生成新数组 | 列表 | 一行代码完成合并 | 需转换为列表,多一步操作 |
extend() 方法 | 修改原数组 | 整个数组/可迭代对象 | 高效,一次性合并大量元素 | 不返回新数组,只修改原数组 |
数组方法
Python 的 array
模块提供了一种高效的数组对象类型,用于存储同质元素(如整数、浮点数、字符),比列表更节省内存。
创建数组的语法如下:
import arrayarr = array.array(typecode, [initializer1, initializer2, ...])
- typecode:单字符,定义数组元素类型,如
'i'
表示整数,'f'
表示浮点数,'u'
表示 Unicode 字符 - initializer:可选的初始化值列表
数组方法主要分为以下几类:
- 添加和删除元素
- 信息和工具方法
- 操作数组元素的方法
- 数组转换方法
增加和删除元素的方法
方法 | 功能 | 示例 |
---|---|---|
append(x) | 在数组末尾增加元素 x | a.append(40) |
extend(iterable) | 将可迭代对象的所有元素追加到数组末尾 | a.extend([50, 60]) |
insert(i, x) | 在索引 i 位置插入元素 x | a.insert(1, 15) |
pop([i]) | 移除并返回索引 i 的元素,若不指定索引则移除最后一个 | a.pop() 或 a.pop(2) |
remove(x) | 移除数组中首次出现的元素 x | a.remove(20) |
示例:
import array as arra = arr.array('i', [10, 20, 30])
a.append(40)
a.extend([50, 60])
a.insert(1, 15)
a.pop()
a.remove(20)
print(a) # 输出: array('i', [10, 15, 30, 40, 50])
信息和工具方法
方法 | 功能 | 示例 |
---|---|---|
buffer_info() | 返回 (地址, 元素个数) 的元组 | a.buffer_info() |
count(x) | 统计元素 x 出现的次数 | a.count(10) |
index(x[, start[, stop]]) | 返回元素 x 的最小索引,可指定搜索范围 | a.index(30) |
示例:
print(a.buffer_info()) # 输出类似: (139947472828160, 5)
print(a.count(10)) # 输出: 1
print(a.index(30)) # 输出: 2
操作数组元素的方法
方法 | 功能 | 示例 |
---|---|---|
reverse() | 将数组元素顺序反转 | a.reverse() |
byteswap() | 对数组元素进行字节交换,用于不同字节序的机器 | a.byteswap() |
示例:
a.reverse()
print(a) # 输出: array('i', [50, 40, 30, 15, 10])
数组的转换方法
方法 | 功能 | 示例 |
---|---|---|
frombytes(buffer) | 从字节对象解析数据并追加到数组 | a.frombytes(b'\x01\x00\x00\x00') |
tobytes() | 将数组转换为字节表示 | b = a.tobytes() |
fromfile(f, n) | 从文件中读取 n 个元素并追加 | a.fromfile(f, 10) |
tofile(f) | 将数组所有元素写入文件 | a.tofile(f) |
fromlist(list) | 从列表中追加元素 | a.fromlist([70, 80]) |
tolist() | 将数组转换为列表 | lst = a.tolist() |
fromunicode(s) | 将 Unicode 字符串追加到数组,类型必须 'u' | a.fromunicode('abc') |
tounicode() | 将数组转换为 Unicode 字符串,类型必须 'u' | s = a.tounicode() |
示例:
import array as arra = arr.array('i', [10, 20, 30])
lst = a.tolist()
print(lst) # 输出: [10, 20, 30]b = arr.array('i')
b.fromlist([40, 50])
print(b) # 输出: array('i', [40, 50])
如果数组类型是 'u'
(Unicode),可以做字符串操作:
a = arr.array('u', 'hello')
a.fromunicode(' world')
print(a.tounicode()) # 输出: 'hello world'