参考整理:https://blog.csdn.net/m0_37816922/article/details/121181511
在Python中有句话叫做,学会使用迭代器,代表着你距离高级程序员更进了一步。
Itertools综合了大量便捷易用的迭代器,并提供next用于访问迭代器,list用于转换迭代器为array类型。
一、源码及使用说明
Itertools库
mono
复制
引用方法:如果采用pia install itertools下载的话使用(参考链接)暂未开放下载
#Include <itertools\itertools>
否则正常可以将文件放到同级目录
#include itertools.ahk
使用时采用以下方法
iter := itertools.xxx([xxx])
源码:
; Author: Mono
; Time: 2022.09.22
; Version: 1.0.0
Class Itertools
{
Class Accumulate
{
__New(arr, function := -1)
{
if arr is String
arr := StrSplit(arr)
this.arr := arr
this.pos := 1
this.ret := 0
this.function := (function == -1) ? add : function
add(x, y)
{
Return x + y
}
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
if this.pos > this.arr.Length
{
this.pos := 1
Return False
}
if this.pos == 1
{
this.ret := this.arr[this.pos++]
ret := this.ret
}
else
{
this.ret := this.function.call(this.ret, this.arr[this.pos++])
ret := this.ret
}
Return True
}
}
}
Class Chain
{
__New(arr*)
{
if arr is String
arr := StrSplit(arr)
this.arr := arr
this.pos := 1
this.pos2d := 1
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
if this.pos2d > this.arr[this.pos].Length
{
this.pos2d := 1
this.pos++
}
if this.pos > this.arr.Length
{
this.pos := 1
Return False
}
ret := this.arr[this.pos][this.pos2d++]
Return True
}
}
}
Class Combinations
{
__New(arr, times)
{
if arr is String
arr := StrSplit(arr)
this.arr := arr
this.pos := []
this.times := times
Loop this.times
this.pos.Push(1)
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
flag := 0
Loop this.times - 1
{
if this.pos[-A_Index] > this.arr.Length
{
this.pos[-A_Index] := 1
this.pos[-A_Index - 1]++
}
}
if this.pos[1] > this.arr.Length
{
this.pos[1] := 1
Return False
}
while !flag
{
tmp := []
tmp2 := Map()
Loop this.times
{
tmpflag := (A_Index == 1) ? 0 : (this.arr[this.pos[A_Index]] > this.arr[this.pos[A_Index - 1]]) ? 0 : 1
if tmp2.Has(this.arr[this.pos[A_Index]]) || tmpflag
{
this.pos[-1]++
Loop this.times - 1
{
if this.pos[-A_Index] > this.arr.Length
{
this.pos[-A_Index] := 1
this.pos[-A_Index - 1]++
}
}
if this.pos[1] > this.arr.Length
{
this.pos[1] := 1
Return False
}
Continue 2
}
else
{
tmp.Push(this.arr[this.pos[A_Index]])
tmp2[this.arr[this.pos[A_Index]]] := 0
}
}
ret := tmp
this.pos[-1]++
flag := 1
}
Return True
}
}
}
Class Combinations_With_Replacement
{
__New(arr, times)
{
if arr is String
arr := StrSplit(arr)
this.arr := arr
this.pos := []
this.times := times
Loop this.times
this.pos.Push(1)
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
flag := 0
Loop this.times - 1
{
if this.pos[-A_Index] > this.arr.Length
{
this.pos[-A_Index] := 1
this.pos[-A_Index - 1]++
}
}
if this.pos[1] > this.arr.Length
{
this.pos[1] := 1
Return False
}
while !flag
{
tmp := []
Loop this.times
{
tmpflag := (A_Index == 1) ? 0 : (this.arr[this.pos[A_Index]] >= this.arr[this.pos[A_Index - 1]]) ? 0 : 1
if tmpflag
{
this.pos[-1]++
Loop this.times - 1
{
if this.pos[-A_Index] > this.arr.Length
{
this.pos[-A_Index] := 1
this.pos[-A_Index - 1]++
}
}
if this.pos[1] > this.arr.Length
{
this.pos[1] := 1
Return False
}
Continue 2
}
else
tmp.Push(this.arr[this.pos[A_Index]])
}
ret := tmp
this.pos[-1]++
flag := 1
}
Return True
}
}
}
Class Compress
{
__New(arr, flags)
{
if arr is String
arr := StrSplit(arr)
this.arr := arr
this.flags := flags
this.pos := 1
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
while (this.pos <= this.flags.Length) && (!this.flags[this.pos])
this.pos++
if this.pos > this.arr.Length
{
this.pos := 1
Return False
}
ret := this.arr[this.pos++]
Return True
}
}
}
Class Count
{
__New(init, step := 1)
{
this.start := init
this.step := step
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
ret := this.start
this.start += this.step
Return True
}
}
}
Class Cycle
{
__New(arr)
{
if arr is String
arr := StrSplit(arr)
this.arr := arr
this.pos := 1
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
ret := this.arr[this.pos]
this.pos := ((this.pos + 1) > this.arr.Length) ? 1 : (this.pos + 1)
Return True
}
}
}
Class Dropwhile
{
__New(function, arr)
{
if arr is String
arr := StrSplit(arr)
this.function := function
this.flag := 0
this.arr := arr
this.pos := 1
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
while (!this.flag) && (this.pos <= this.arr.Length) && (this.function.call(this.arr[this.pos]))
this.pos++
if this.pos > this.arr.Length
{
this.pos := 1
Return False
}
this.flag := 1
ret := this.arr[this.pos++]
Return True
}
}
}
Class Filterfalse
{
__New(function, arr)
{
if arr is String
arr := StrSplit(arr)
this.function := function
this.arr := arr
this.pos := 1
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
while (this.pos <= this.arr.Length) && (this.function.call(this.arr[this.pos]))
this.pos++
if this.pos > this.arr.Length
{
this.pos := 1
Return False
}
ret := this.arr[this.pos++]
Return True
}
}
}
Class Ifilter
{
__New(Func, Iterable)
{
this.Func := Func
this.Iterable := Iterable
}
__Enum(Number)
{
this.Pos := this.Iterable
Return Fn
Fn(&Res := 0)
{
Res := Next(this.Pos)
While !this.Func.Call(Res)
Res := Next(this.Pos)
Return 1
}
}
}
Class IfilterFalse
{
__New(Func, Iterable)
{
this.Func := Func
this.Iterable := Iterable
}
__Enum(Number)
{
this.Pos := this.Iterable
Return Fn
Fn(&Res := 0)
{
Res := Next(this.Pos)
While this.Func.Call(Res)
Res := Next(this.Pos)
Return 1
}
}
}
Class Islice
{
__New(arr, start, stop := "", step := 1)
{
if arr is String
arr := StrSplit(arr)
if !step
Throw ValueError("Step cannot be 0.")
if stop == ""
{
tmp := start
start := 1
stop := tmp
}
this.arr := arr
this.index := 0
this.start := start
this.stop := stop
this.step := step
this.length := Max(0, (this.stop - this.start) // Abs(this.step) + 1)
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
if !this.Length
{
this.length := Max(0, (this.stop - this.start) // Abs(this.step) + 1)
this.index := 0
Return False
}
ret := this.arr[this.start + this.index * this.step]
this.index++
Return this.length--
}
}
}
Class Pairwise
{
__New(arr)
{
if arr is String
arr := StrSplit(arr)
this.arr := arr
this.pos := 1
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
if this.pos >= this.arr.length
{
this.pos := 1
Return False
}
ret := [this.arr[this.pos++], this.arr[this.pos]]
Return True
}
}
}
Class Permutations
{
__New(arr, times)
{
if arr is String
arr := StrSplit(arr)
this.arr := arr
this.pos := []
this.times := times
Loop this.times
this.pos.Push(1)
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
flag := 0
Loop this.times - 1
{
if this.pos[-A_Index] > this.arr.Length
{
this.pos[-A_Index] := 1
this.pos[-A_Index - 1]++
}
}
if this.pos[1] > this.arr.Length
{
this.pos[1] := 1
Return False
}
while !flag
{
tmp := []
tmp2 := Map()
Loop this.times
{
if tmp2.Has(this.arr[this.pos[A_Index]])
{
this.pos[-1]++
Loop this.times - 1
{
if this.pos[-A_Index] > this.arr.Length
{
this.pos[-A_Index] := 1
this.pos[-A_Index - 1]++
}
}
if this.pos[1] > this.arr.Length
{
this.pos[1] := 1
Return False
}
Continue 2
}
else
{
tmp.Push(this.arr[this.pos[A_Index]])
tmp2[this.arr[this.pos[A_Index]]] := 0
}
}
ret := tmp
this.pos[-1]++
flag := 1
}
Return True
}
}
}
Class Product
{
__New(arr*)
{
For i in arr
{
if i is String
arr[A_Index] := StrSplit(i)
}
this.arr := arr
this.pos := []
Loop this.arr.Length
this.pos.Push(1)
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
Loop this.arr.Length - 1
{
if this.pos[-A_Index] > this.arr[-A_Index].Length
{
this.pos[-A_Index] := 1
this.pos[-A_Index - 1]++
}
}
if this.pos[1] > this.arr[1].Length
{
this.pos[1] := 1
Return False
}
tmp := []
Loop this.arr.Length
tmp.Push(this.arr[A_Index][this.pos[A_Index]])
ret := tmp
this.pos[-1]++
Return True
}
}
}
Class Range
{
__New(Start, Stop := "", Step := 1)
{
if !Step
Throw ValueError("Step cannot be 0.")
if Stop == ""
{
Tmp := Start
Start := 1
Stop := Tmp
}
this.Length := Max(0, (Stop - Start) // Abs(Step) + 1)
this.Start := Start
this.Stop := Stop
this.Step := Step
}
__Enum(_)
{
this.LoopTimes := this.Length
this.Index := 0
Return Fn
Fn(&Idx := 0, &Value := 0)
{
if !this.LoopTimes
Return False
Idx := (IsSet(Value)) ? this.Start + this.Index * this.Step : this.Index + 1
Value := this.Start + this.Index * this.Step
this.Index++
Return this.LoopTimes--
}
}
Array()
{
Ret := []
Loop this.Length
{
if this.Step > 0
Ret.Push(this.Start + (A_Index - 1) * this.Step)
else
Ret.Push(this.Stop + (A_Index - 1) * this.Step)
}
Return Ret
}
}
Class Repeat
{
__New(value, times := -1)
{
this.value := value
this.times := times
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
ret := this.value
if !this.times
Return False
this.times--
Return True
}
}
}
Class Takewhile
{
__New(function, arr)
{
if arr is String
arr := StrSplit(arr)
this.function := function
this.arr := arr
this.pos := 1
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
if this.pos > this.arr.Length
{
this.pos := 1
Return False
}
if this.function.call(this.arr[this.pos])
ret := this.arr[this.pos++]
else
{
this.pos := 1
Return False
}
Return True
}
}
}
Class Zip_Longest
{
__New(arr*)
{
if !(arr[-1] is Array)
this.fillvalue := arr.pop()
else
this.fillvalue := 0
this.maxlength := 0
For i in arr
{
if i is String
{
i := StrSplit(i)
arr[A_Index] := i
}
if i.Length > this.maxlength
this.maxlength := i.Length
}
this.arr := arr
this.pos := 1
}
__Enum(_)
{
Return Fn
Fn(&ret)
{
if this.pos > this.maxlength
{
this.pos := 1
Return False
}
tmp := []
For i in this.arr
{
if i.Length >= this.pos
tmp.Push(i[this.pos])
else
tmp.Push(this.fillvalue)
}
ret := tmp
this.pos++
Return True
}
}
}
}
Next(iter)
{
For i in iter
Return i
}
List(iter)
{
Ret := []
For i in iter
Ret.Push(i)
Return Ret
}
二、函数介绍
itertools
中包有三个无穷迭代器,分别是count
, cycle
和repeat
。需要注意一点就是,千万别对无穷迭代器用list
。具体实例查看python相关用法,基本实现一致。
#print函数需要引用#include print.ahk
itertools := it
>>> x := it.count(0,2) #两个参量分别是初始值和步长,
>>> next(x)
0
>>> for i in it.range(3)
print(next(x),end:=' ')
...
2 4 6
>>> x := it.count(3) #步长为可选参量,默认为1
>>> for i in it.range(3)
print(next(x),end:=' ')
...
3 4 5
>>> for _ in it.range(10)
print(next(x), end:=' ')
...
6 7 8 9 10 11 12 13 14 15
>>> c := it.cycle([1,2,3]) #对1,2,3进行无穷的循环
>>> next(c)
1
>>> for i in it.range(10)
print(next(c),end:=' ')
...
2 3 1 2 3 1 2 3 1 2
>>> c := it.cycle("love") #其参数也可以为字符串
>>> for i in it.range(10)
print(next(c), end:=' ')
...
l o v e l o v e l o
>>> r := it.repeat(10,3) #对10循环3次
>>> list(r)
[10, 10, 10]
>>> r := it.repeat(10) #如果只有一个参数,则无穷循环
>>> for i in range(10)
print(next(r), end:=' ')
...
10 10 10 10 10 10 10 10 10 10
>>> r := it.repeat([1,2],3)
>>> list(r)
[[1, 2], [1, 2], [1, 2]]
accumulate(lst,func) |
累加求和 | |
chain(as,bs,...) |
列表连加器 | |
compress(d,s) |
根据s的真值取d | |
filterfalse(func,lst) |
lst中func为假的元素 | |
dropwhile(func,lst) |
lst中,自func为假之后的元素 | |
takewhile(func,lst) |
lst中,自func为假之前的元素 | |
islice(lst,[s,]e,[,step]) |
索引 |
?