
本文介绍多种 pythonic 方式从列表中提取两个(或多个)非连续切片,如 [0:3] 和 [5:7],涵盖拼接切片、索引列表推导、numpy 高级索引等方法,并对比其可读性、性能与适用场景。
本文介绍多种 pythonic 方式从列表中提取两个(或多个)非连续切片,如 [0:3] 和 [5:7],涵盖拼接切片、索引列表推导、numpy 高级索引等方法,并对比其可读性、性能与适用场景。
在 Python 中,原生列表不支持类似 R 的 c(1:3, 6:7) 式多段索引语法,但可通过多种清晰、高效的方式实现等效功能。以下是几种主流且实用的方法,按推荐度与适用性排序:
✅ 方法一:切片拼接(最 Pythonic,推荐首选)
直接使用 + 拼接两个(或多个)切片,语义直观、无副作用、代码简洁:
target_list = [1, 2, 3, 4, 5, 6, 7, 8, 9] subset_list = target_list[:3] + target_list[4:7] # 注意:R 的 1:3 对应 Python 的 [0:3],6:7 对应 [5:7] print(subset_list) # [1, 2, 3, 6, 7]
⚠️ 注意:R 索引从 1 开始,Python 从 0 开始。R 中 c(1:3, 6:7) 对应 Python 索引 [0:3] + [5:7](即 target_list[0:3] + target_list[5:7]),上例中 target_list[4:7] 实际取的是索引 4、5、6 → [5, 6, 7],若目标为 [1,2,3,6,7](跳过索引 4 的元素 5),则应写为 target_list[:3] + target_list[5:7]。
✅ 方法二:显式索引列表推导(灵活通用)
适用于任意离散索引组合(包括重复、乱序、动态生成):
indices = list(range(3)) + list(range(5, 7)) # [0,1,2,5,6] subset_list = [target_list[i] for i in indices] print(subset_list) # [1, 2, 3, 6, 7]
也可用 itertools.chain 提升可读性:
from itertools import chain indices = chain(range(3), range(5, 7)) subset_list = [target_list[i] for i in indices]
⚠️ 方法三:就地删除(仅适用于简单场景,不推荐)
通过先截断再删除中间元素实现,但会修改副本、逻辑隐晦、难以扩展:
subset_list = target_list[:7].copy() # 先取前7个 del subset_list[3] # 删除索引3处的元素(即原列表中的第4个元素) # 若需删多个:del subset_list[3:5] → 删除索引3和4
该方式易出错(索引偏移)、不可逆、缺乏表达力,仅作技术参考,生产环境应避免。
? 进阶方案:NumPy 高级索引(适合数值计算场景)
当处理大型数值数组时,NumPy 支持类 R 的整数数组索引,性能卓越:
import numpy as np arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]) indices = np.r_[0:3, 5:7] # 等价于 np.concatenate([np.arange(3), np.arange(5,7)]) subset_arr = arr[indices] print(subset_arr.tolist()) # [1, 2, 3, 6, 7]
? 提示:np.r_ 是 NumPy 提供的便捷语法糖,专为构造分段索引而设计,语义接近 R,但需引入额外依赖。
总结与选型建议
- 日常开发首选:slice + slice 拼接(方法一),零依赖、高可读、符合 Python 习惯;
- 复杂索引需求:显式索引列表推导(方法二),灵活可控,易于调试;
- 科学计算场景:NumPy 高级索引(进阶方案),兼顾表达力与性能;
- 避免使用:就地删除法——违反函数式思想,易引发维护陷阱。
无论选择哪种方式,请始终注意 Python 的 0 起始索引与左闭右开区间特性,确保与 R 或其他语言的索引映射准确无误。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











