迭代工具 - IterUtil

由来

Python 的 itertools 模块功能强大但 API 较底层。IterUtil 提供常用的 itertools recipes(迭代器配方),兼容 Python 3.8,无需依赖 3.10+ 的 itertools.pairwise

方法

取值

from hutool import IterUtil

IterUtil.take(3, range(10))        # [0, 1, 2]
IterUtil.take(5, "Hello")          # ['H', 'e', 'l', 'l', 'o']

IterUtil.tail(3, range(10))        # [7, 8, 9]

IterUtil.nth(range(10), 3)         # 3
IterUtil.nth(range(3), 10)         # None(越界)
IterUtil.nth(range(3), 10, -1)     # -1(自定义默认值)

IterUtil.get([10, 20, 30], 1)         # 20
IterUtil.get_first([10, 20])           # 10
IterUtil.get_first_none_null([None, 1])  # 1
IterUtil.first_match([1, 2, 3], lambda x: x > 2)  # 3
IterUtil.get_element_type([1, 2])      # <class 'int'>

判断与统计

IterUtil.all_equal([1, 1, 1])                       # True
IterUtil.all_equal([1, 2, 1])                       # False
IterUtil.is_empty([])                               # True
IterUtil.is_not_empty([1])                          # True
IterUtil.has_null([1, None, 3])                     # True
IterUtil.is_all_null([None, None])                  # True

IterUtil.quantify([1, 2, 3, 4], lambda x: x % 2 == 0)       # 2(偶数个数)
IterUtil.count_map(["a", "b", "a"])                         # {"a": 2, "b": 1}
IterUtil.field_value_map([{"n": "a", "v": 1}], "n", "v")    # {"a": 1}

变换

# 展平一层嵌套
list(IterUtil.flatten([[1, 2], [3, 4], [5]]))  # [1, 2, 3, 4, 5]

# 相邻配对
list(IterUtil.pairwise("ABC"))  # [('A', 'B'), ('B', 'C')]

# 按固定长度分组(不足用 fillvalue 填充)
list(IterUtil.grouper("ABCDEFG", 3, 'x'))
# [('A','B','C'), ('D','E','F'), ('G','x','x')]

# 交替轮询
list(IterUtil.roundrobin("ABC", "D", "EF"))
# ['A', 'D', 'E', 'B', 'F', 'C']

IterUtil.to_map([("a", 1)], lambda x: x[0], lambda x: x[1])  # {"a": 1}
IterUtil.to_list(range(3))  # [0, 1, 2]

分组与幂集

# 按谓词分为两组
f, t = IterUtil.partition(lambda x: x % 2, range(5))
list(f)  # [0, 2, 4]
list(t)  # [1, 3]

# 幂集(所有子集)
list(IterUtil.powerset([1, 2, 3]))
# [(), (1,), (2,), (3,), (1,2), (1,3), (2,3), (1,2,3)]

去重

# 保序去重
list(IterUtil.unique_everseen("AAAABBBCCDAABBB"))  # ['A','B','C','D']

# 带键函数的去重
list(IterUtil.unique_everseen("ABBCcAD", str.lower))  # ['A','B','C','D']

其他

# 拼接
IterUtil.join([1, 2, 3], "-")  # "1-2-3"

# 映射/过滤
IterUtil.edit([1, 2, 3], lambda x: x * 2)  # [2, 4, 6]
IterUtil.filter_([1, 2, 3, 4], lambda x: x > 2)  # [3, 4]
IterUtil.for_each([1, 2], print)

# 工具
IterUtil.size(range(100))            # 100
IterUtil.is_equal_list([1, 2], [1, 2])  # True
IterUtil.to_str([1, 2, 3], "-")       # "1-2-3"

前置追加

# prepend — 在迭代器前面追加元素
list(IterUtil.prepend("start", [1, 2, 3]))  # ["start", 1, 2, 3]

表格化输出

# tabulate — 将数据格式化为表格
IterUtil.tabulate([["Alice", 30], ["Bob", 25]], headers=["Name", "Age"])
# Name    Age
# ------- ---
# Alice   30
# Bob     25

消费迭代器

# consume — 消费迭代器(执行操作,不返回结果)
IterUtil.consume(range(5), print)
# 0 1 2 3 4

None 填充

# padNone — 无限补充 None
list(IterUtil.take(5, IterUtil.pad_none([1, 2])))  # [1, 2, None, None, None]

循环重复

# nCycles — 循环重复 N 次
list(IterUtil.n_cycles([1, 2, 3], 2))  # [1, 2, 3, 1, 2, 3]

异常终止迭代

# iterExcept — 迭代直到抛出指定异常
d = {"a": 1}
list(IterUtil.iter_except(lambda: d.popitem(), KeyError))  # [("a", 1)]

首个真值

# firstTrue — 返回第一个使谓词为 True 的元素
IterUtil.first_true([1, 2, 3, 4], pred=lambda x: x > 2)  # 3

随机组合

# randomProduct — 随机笛卡尔积元素
IterUtil.random_product([1, 2], ["a", "b"])  # (2, "a")

# randomPermutation — 随机排列
IterUtil.random_permutation([1, 2, 3])  # [3, 1, 2]

# randomCombination — 随机组合
IterUtil.random_combination([1, 2, 3, 4], 2)  # [2, 4]

# nthCombination — 第 N 个组合
IterUtil.nth_combination([1, 2, 3, 4], 2, 0)  # [1, 2]