AHK标准库计划(三)——Itertools库

参考整理: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中包有三个无穷迭代器,分别是countcycle 和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]) 索引

给TA捐赠
共{{data.count}}人
人已捐赠
其他

ahk控制excel随笔之布尔值的差异

2022-9-22 21:33:54

其他

本地文件夹版超级命令发布

2022-9-23 9:43:51

3 条回复 A文章作者 M管理员
  1. AHK中文社区

    ?

  2. AHK中文社区
    11010010给您捐赠了¥1
  3. dbgba
    dbgba给您捐赠了¥2
个人中心
购物车
优惠劵
有新私信 私信列表
搜索