杰瑞科技汇

python itertools 组合

itertools.combinations 是一个非常强大且高效的工具,用于获取一个可迭代对象(如列表、元组、字符串等)中指定长度的所有唯一组合

python itertools 组合-图1
(图片来源网络,侵删)

核心概念

组合 的数学定义是:从一组物品中选取一部分,不考虑顺序,从 A, B, C 中选取 2 个,组合有 (A, B), (A, C), (B, C)(B, A)(A, B) 被视为同一个组合,因此只出现一次。

这与 排列 不同,排列是考虑顺序的。(A, B)(B, A) 是两种不同的排列。

itertools.combinations 正是用来生成这些组合的。


函数签名

itertools.combinations(iterable, r)
  • iterable: 一个可迭代对象,例如列表、元组、字符串等。
  • r: 一个整数,表示每个组合中元素的个数。

返回值:

python itertools 组合-图2
(图片来源网络,侵删)
  • 返回一个迭代器,这个迭代器会产生 r 长度的元组,这些元组是 iterable 的所有可能组合。

基本使用示例

让我们从几个简单的例子开始。

示例 1:从列表中选取 2 个元素

import itertools
data = ['A', 'B', 'C', 'D']
r = 2
# 创建一个组合迭代器
combinations_iterator = itertools.combinations(data, r)
# 迭代器不能直接打印,需要遍历它
print(f"从 {data} 中选取 {r} 个元素的所有组合:")
for combo in combinations_iterator:
    print(combo)
# 输出结果:
# 从 ['A', 'B', 'C', 'D'] 中选取 2 个元素的所有组合:
# ('A', 'B')
# ('A', 'C')
# ('A', 'D')
# ('B', 'C')
# ('B', 'D')
# ('C', 'D')

示例 2:从字符串中选取 3 个字符

字符串本身也是一个可迭代对象,其中每个字符都是一个元素。

import itertools
word = "PQRS"
r = 3
combinations_iterator = itertools.combinations(word, r)
print(f"从字符串 '{word}' 中选取 {r} 个字符的所有组合:")
# 为了方便查看,我们可以将结果转换为列表
print(list(combinations_iterator))
# 输出结果:
# 从字符串 'PQRS' 中选取 3 个字符的所有组合:
# [('P', 'Q', 'R'), ('P', 'Q', 'S'), ('P', 'R', 'S'), ('Q', 'R', 'S')]

示例 3:从数字列表中选取 2 个数字

import itertools
numbers = [10, 20, 30]
r = 2
combinations_iterator = itertools.combinations(numbers, r)
print(f"从 {numbers} 中选取 {r} 个数字的所有组合:")
print(list(combinations_iterator))
# 输出结果:
# 从 [10, 20, 30] 中选取 2 个数字的所有组合:
# [(10, 20), (10, 30), (20, 30)]

重要特性

a) 唯一性

itertools.combinations 不会重复使用 iterable 中的同一个元素,每个元素在一个组合中只能出现一次。

import itertools
data = ['A', 'A', 'B'] # 注意列表中有重复元素 'A'
# 即使输入有重复元素,itertools.combinations 也会根据位置来区分
# 第一个 'A' 和第二个 'A' 是不同的元素
combinations_iterator = itertools.combinations(data, 2)
print(list(combinations_iterator))
# 输出结果:
# [('A', 'A'), ('A', 'B'), ('A', 'B')]
# 解释:
# 1. (第一个'A', 第二个'A')
# 2. (第一个'A', 'B')
# 3. (第二个'A', 'B')

b) 排序性

生成的组合是按照输入 iterable 中元素的原始顺序进行排序的,组合内部的元素顺序也遵循原始顺序,如果 iterable['C', 'A', 'B'],你不会得到 ('A', 'C') 这样的组合。

python itertools 组合-图3
(图片来源网络,侵删)

c) 迭代器而非列表

itertools.combinations 返回的是一个迭代器,这意味着:

  • 节省内存:特别是当 iterable 很大时,它不会一次性在内存中生成所有组合,而是按需生成。
  • 只能遍历一次:迭代器在遍历完后就会耗尽,不能再次使用。
import itertools
data = [1, 2, 3]
combo_iter = itertools.combinations(data, 2)
print("第一次遍历:")
print(list(combo_iter)) # [ (1, 2), (1, 3), (2, 3) ]
print("\n第二次遍历:")
print(list(combo_iter)) # []

与其他 itertools 函数的区别

理解 combinations 与其他相关函数的区别非常重要。

函数名 功能 关键区别 示例 (从 'ABC' 选2个)
combinations(iterable, r) 组合不考虑顺序,元素不重复。 核心:顺序不重要 ('A', 'B'), ('A', 'C'), ('B', 'C')
permutations(iterable, r) 排列考虑顺序,元素不重复。 核心:顺序重要 ('A', 'B'), ('B', 'A'), ('A', 'C'), ('C', 'A'), ('B', 'C'), ('C', 'B')
combinations_with_replacement(iterable, r) 组合不考虑顺序元素可重复 核心:元素可重复 ('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')

combinations vs. permutations 示例

import itertools
data = 'ABC'
r = 2
print("--- combinations (组合) ---")
print(list(itertools.combinations(data, r)))
# 输出: [('A', 'B'), ('A', 'C'), ('B', 'C')]
print("\n--- permutations (排列) ---")
print(list(itertools.permutations(data, r)))
# 输出: [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]

实际应用场景

itertools.combinations 在很多场景下都非常有用,尤其是在需要穷举可能性时。

场景 1:生成密码组合(简单版)

假设你知道一个密码是由 ['a', 'b', 'c', 'd'] 中的 3 个不同字母组成的,你想列出所有可能性。

import itertools
chars = ['a', 'b', 'c', 'd']
length = 3
# 注意:这会生成所有可能的3字母组合,但密码可能是排列,所以还需要进一步处理
# 这里只演示 combinations 的用法
all_combinations = itertools.combinations(chars, length)
# 将元组组合成字符串
passwords = [''.join(p) for p in all_combinations]
print(f"所有可能的 {length} 字母组合:")
print(passwords)
# 输出: ['abc', 'abd', 'acd', 'bcd']

场景 2:找出列表中所有可能的二元组

假设你有一个列表 [1, 2, 3, 4],你想找出所有可能的数对(不重复)来进行某种计算或比较。

import itertools
numbers = [1, 2, 3, 4]
# 找出所有可能的比赛队伍对阵(不考虑主客场)
all_pairings = itertools.combinations(numbers, 2)
print("所有可能的队伍对阵:")
for pairing in all_pairings:
    print(f"队伍 {pairing[0]} vs 队伍 {pairing[1]}")
# 输出:
# 队伍 1 vs 队伍 2
# 队伍 1 vs 队伍 3
# 队伍 1 vs 队伍 4
# 队伍 2 vs 队伍 3
# 队伍 2 vs 队伍 4
# 队伍 3 vs 队伍 4

场景 3:数据采样与测试

在机器学习中,你可能需要从数据集中创建不同的训练/验证集组合来进行交叉验证。

import itertools
features = ['feature_1', 'feature_2', 'feature_3', 'feature_4']
num_features_to_select = 2
# 选择两个特征进行模型训练
feature_sets = itertools.combinations(features, num_features_to_select)
print("要尝试的特征组合:")
print(list(feature_sets))
# 输出: [('feature_1', 'feature_2'), ('feature_1', 'feature_3'), ...]

  • itertools.combinations(iterable, r) 是 Python 标准库中用于生成无序组合的利器。
  • 它返回一个迭代器,按需生成组合,内存效率高。
  • 组合中的元素不重复,且顺序不重要
  • 当你需要从一组事物中选取一部分,且不关心它们的选取顺序时,itertools.combinations 是你的首选。
分享:
扫描分享到社交APP
上一篇
下一篇