【新手向】基础类型加强Array篇——AHKType库(一)

很多新手入坑后对于Array的操作用不明白,Push、Pop等函数略为抽象,这里提供Array的增强版本,不需要更多的函数引用,在原有的Array基础上,你将有更多的函数用来操作Array数组。

下载地址:

【新手向】AHKType库示例与下载

更新时间:2022.09.07

使用介绍:

; 属性
1)Dims——返回Array深度
2)NDim——返回Array深度(与Dims相同)
3)Max——返回Array中最大项
4)MaxDim——返回Array中最大深度
5)MaxDimIndex——返回Array中最大深度对应项
6)Min——返回Array中最小项
7)Product——返回Array所有数字元素之积
8)Shape——返回Array的形状,这一操作会对Array进行规格化

; 函数(为保证完整性,以下函数均会直接改变Array对象本身)
1)Append(Content*)——在Array尾部添加对象,同Push
2)Count(Obj)——返回Array中Obj数量
3)Extend(Extend_Lst*)——在Array尾部延伸输入内容,与Append有区别
4)Index(Obj)——返回Array中Obj首次出现位置,若不存在返回-1
5)Insert(Index, Obj*)——在Array指定位置插入若干对象
6)IReshape(Shape)——将Array重构为Shape形状,这一变形不会对Array进行规格化
7)Reshape(Shape)——将Array重构为Shape形状,这一变形会对Array进行规格化
8)Ravel()——将Array拉伸为一维,这一变形不会对Array进行规格化
9)Standardization()——将Array规格化,Array形状由每一层最大深度确定,缺位补0
10)Item(Pos*)——通过多维方式访问Array
11)SetItem(Pos*, Value)——通过多维方式设置Array项值
12)MaxLength(Dim := 1)——获取Array在某一个Dim的最大长度
13)Remove(Obj*)——移除Array中若干Obj项
14)Reverse()——将Array倒置
15)Swap(Index1, Index2)——将Array中的第Index1和Index2项交换
16)Sort(cmp := "", key := "", reverse := False)——排列Array
cmp默认为升序比较函数(函数参数需要两个,函数返回值大于零表示排列优先)
key默认为空,(函数参数为1个,函数返回值大的表示排列优先)
reverse默认为否,若为真则反转排列后列表
#Include AHKType.ahk

; 测试
a := [1, 2, [3, 4]]
Print(a.Dims)
Print(a.NDim)

a := [1, 2, [3, 4], [5, 6, [7, 8]]]
b := [1, 2, [3, 4], [5, 6, [7, 8]]]
a.Reshape([3, 2, 4])
b.IReshape([2, 4])
Print(a)
Print(b)

a := [1, 2, [3, 4], [5, 6, [7, 8]]]
a.ravel()
Print(a)

; Sort函数测试
a := [2, 1, 4 ,5]
Print(a.Sort("reverse=1"))
b := [2, 1, 4 ,5]
Print(b.Sort())
c := [2, 1, 4 ,5]
Print(c.Sort(comp))
d := ["456", "123", "1237" ,"00"]
Print(d.Sort("key=Len"))
; 上一行等价于Print(d.Sort(, Len))

comp(x, y)
{
    if x < y
        return 1
    else if x > y
        return -1
    else
        return 0
}

Len(x)
{
    if x is Array
        Return x.Length
    
    else if x is String
        Return StrLen(x)
    
    Return x
}

AHKType源码

; Author: Mono
; Time: 2022.09.08
; Version: 1.0.0

#Include Print.ahk
; Init DefProp
DefProp := {}.DefineProp


; Redefine Dims
0.0.Base.Dims := 0
0.Base.Dims := 0
"".Base.Dims := 0
Object().Base.Dims := 0
DefProp([].Base, "Dims", {Get: GetArrDims})


; Redefine NDim
0.0.Base.NDim := 0
0.Base.NDim := 0
"".Base.NDim := 0
Object().Base.NDim := 0
DefProp([].Base, "NDim", {Get: GetArrDims})


; Redefine Array
DefProp([].Base, "Append", {Get: ArrAppend})
DefProp([].Base, "Count", {Get: ArrCount})
DefProp([].Base, "Extend", {Get: ArrExtend})
DefProp([].Base, "Index", {Get: ArrIndex})
DefProp([].Base, "Insert", {Get: ArrInsert})
DefProp([].Base, "IReshape", {Get: ArrIReshape})
DefProp([].Base, "Item", {Get: GetArrItem})
DefProp([].Base, "Max", {Get: GetArrMax})
DefProp([].Base, "MaxDim", {Get: GetArrMaxDim})
DefProp([].Base, "MaxDimIndex", {Get: GetArrMaxDimIndex})
DefProp([].Base, "MaxLength", {Get: GetArrMaxLength})
DefProp([].Base, "Min", {Get: GetArrMin})
DefProp([].Base, "Product", {Get: GetArrProduct})
DefProp([].Base, "Ravel", {Get: ArrRavel})
DefProp([].Base, "Remove", {Get: ArrRemove})
DefProp([].Base, "Reshape", {Get: ArrReshape})
DefProp([].Base, "Reverse", {Get: ArrReverse})
DefProp([].Base, "SetItem", {Get: SetArrItem})

if !HasProp([], "Sort")
    DefProp([].Base, "Sort", {Get: ArrSort})

DefProp([].Base, "Shape", {Get: GetArrShape})
DefProp([].Base, "Standardization", {Get: ArrStandardization})
DefProp([].Base, "Swap", {Get: ArrSwap})

;Redefine Map

; Redefine Object
DefProp({}.Base, "Map", {Get: Object2Map})

; Redefine String
DefProp("".Base, "Array", {Get: StrSplit})

; Related Func
ArrAppend(this)
{
    Return ArrAppend2
}

ArrAppend2(this, Content*)
{
    this.Push(Content*)
}

ArrCount(this)
{
    Return ArrCount2
}

ArrCount2(this, Obj)
{
    Return_Count := 0
        
    For i in this
    {
        if !ListCmp(i, Obj)
            Return_Count++
    }
    
    Return Return_Count
}

ArrExtend(this)
{
    Return ArrExtend2
}

ArrExtend2(this, Extend_Lst*)
{
    Loop Extend_Lst.Length
    {
        if !Extend_Lst[A_Index].Dims
            this.Push(Extend_Lst[A_Index])
        
        else
        {
            For i in Extend_Lst[A_Index]
                this.Push(i)
        }
    }
    
    Return this
}

ArrIndex(this)
{
    Return ArrIndex2
}

ArrIndex2(this, Obj)
{
    Index := -1
    
    For i in this
    {
        if !ListCmp(i, Obj)
        {
            Index := A_Index
            Break
        }
    }
    
    Return Index
}

ArrInsert(this)
{
    Return ArrInsert2
}

ArrInsert2(this, Index, Obj*)
{
    this.InsertAt(Index, Obj*)
    
    Return this
}

ArrIReshape(this)
{
    Return ArrIReshape2
}

ArrIReshape2(this, Shape)
{
    this.Ravel()
    
    Return this.Reshape(Shape)
}

ArrRavel(this)
{
    Return ArrRavel2
}

ArrRavel2(this)
{
    if !this.MaxDim
        Return this
    
    Tmp := []
    
    For i in this
    {
        if !i.Dims
            Tmp.Push(i)
        
        else
            Tmp.Extend(ArrRavel2(i))
    }
    
    this.Length := 0
    
    For j in Tmp
        this.Push(j)
    
    Return this
}

ArrRemove(this)
{
    Return ArrRemove2
}

ArrRemove2(this, Obj*)
{
    Loop Obj.Length
    {
        Index := this.Index(Object[A_Index])
        
        if Index != -1
            this.Pop(Index)
    }
    
    Return this
}

ArrReshape(this)
{
    Return ArrReshape2
}

ArrReshape2(this, Shape)
{
    OldShape := this.Shape
    TmpShape := Shape.Clone()
    
    if OldShape.Product !== Shape.Product
        Return this
    
    if Shape.Length == 1
        Return this.Ravel()
    
    this.Ravel()
    Tmpthis := this.Clone()
    Tmp := []
    LoopTimes := TmpShape.RemoveAt(1)
    
    Loop LoopTimes
    {
        Tmp2 := []
        Loop TmpShape.Product
            Tmp2.Push(Tmpthis.RemoveAt(1))
        
        Tmp.Push(ArrReshape2(Tmp2, TmpShape))
    }
    
    this.Length := 0
    
    For j in Tmp
        this.Push(j)
    
    Return this
}

ArrReverse(this)
{
    Return ArrReverse2
}

ArrReverse2(this)
{
    Loop this.Length // 2
        this.Swap(A_Index, this.Length - A_Index + 1)
    
    Return this
}

ArrSort(this)
{
    Return ArrSort2
}

ArrSort2(this, cmp := "", key := "", reverse := False)
{
    if (key is String) && InStr(key, "reverse")
        reverse := Trim(StrSplit(key, "=")[2])
    
    if (cmp is String) && InStr(cmp, "key")
        key := %Trim(StrSplit(cmp, "=")[2])%
    
    if (cmp is String) && InStr(cmp, "reverse")
        reverse := Trim(StrSplit(cmp, "=")[2])
    
    if !(cmp is Func)
        cmp := ListCmp
    
    if !key
    {
        Loop this.Length
        {
            Index := A_Index
            
            Loop this.Length - Index
            {
                if cmp(this[Index], this[A_Index + Index]) > 0
                    this.Swap(Index, A_Index + Index)
            }
        }
    }
    
    else
    {
        Loop this.Length
        {
            Index := A_Index
            
            Loop this.Length - Index
            {
                if key(this[Index]) > key(this[A_Index + Index])
                    this.Swap(Index, A_Index + Index)
            }
        }
    }
    
    if reverse
        this.Reverse()
    
    Return this
}

ArrStandardization(this)
{
    Return ArrStandardization2
}

ArrStandardization2(this)
{
    if this.Dims == 1
        Return this
    
    Shape := []
    
    Loop this.Dims
        Shape.Push(this.MaxLength(A_Index))
    
    Ret := ArrStandardShape(this, Shape)
    
    For i in Ret
        this[A_Index] := i
    
    Return this
}

ArrStandardShape(this, Shape)
{
    if Shape.Length == 1
    {
        Tmp := this.Dims ? this : [this]
        
        Loop Shape[1] - Tmp.Length
            Tmp.Push(0)
        
        Return Tmp
    }
    
    Tmp := this.Dims ? this : [this]
    
    Loop Shape[1] - Tmp.Length
        Tmp.Push(0)
    
    TmpShape := Shape.Clone()
    TmpShape.RemoveAt(1)
    
    For i in Tmp
        Tmp[A_Index] := ArrStandardShape(i, TmpShape)
    
    Return Tmp
}

ArrSwap(this)
{
    Return ArrSwap2
}

ArrSwap2(this, Index1, Index2)
{
    if Index1 > this.Length || Index2 > this.Length || Index1 == Index2
        Return this
    
    Temp := this[Index1]
    this[Index1] := this[Index2]
    this[Index2] := Temp
    
    Return this
}

GetArrDims(this)
{
    Tmp := []
    
    For i in this
        Tmp.Push(HasProp(i, "Dims") ? i.Dims : 0)
    
    Return Max(Tmp*) + 1
}

GetArrItem(this)
{
    Return GetArrItem2
}

GetArrItem2(this, Pos*)
{
    Ret := this.Clone()
    
    Loop Pos.Length
        Ret := Ret[Pos[A_Index]]
    
    Return Ret
}

GetArrMax(this)
{
    Tmp := this.Clone()
    
    Return this.Length ? Tmp.Sort()[-1] : ""
}

GetArrMaxDim(this)
{
    Return this[GetArrMaxDimIndex(this)].Dims
}

GetArrMaxLength(this)
{
    Return GetArrMaxLength2
}

GetArrMaxLength2(this, Dim := 1)
{
    if !this.Dims || Dim > this.Dims
        Return 1
    
    if Dim == 1
        Return this.Length
    
    MaxLength := 1
    Dim--
    
    For i in this
    {
        if GetArrMaxLength2(i, Dim) > MaxLength
            MaxLength := GetArrMaxLength2(i, Dim)
    }
    
    Return MaxLength
}

GetArrMaxDimIndex(this)
{
    MaxDim := 0
    MaxDimIndex := 1
    
    For i in this
    {
        if i.Dims > MaxDim
        {
            MaxDim := i.Dims
            MaxDimIndex := A_Index
        }
    }
    
    Return MaxDimIndex
}

GetArrMin(this)
{
    Tmp := this.Clone()
    
    Return this.Length ? Tmp.Sort()[1] : ""
}

GetArrProduct(this)
{
    Ret := 1
    
    For i in this
    {
        if Ret == 0
            Return Ret
        
        if i.Dims
            Ret *= GetArrProduct(i)
        
        else
        {
            Try
                Ret *= i
        }
    }
    
    Return Ret
}

GetArrShape(this)
{
    this.Standardization()
    
    Tmp := this.Clone()
    Shape := []
    
    While Tmp.MaxDim
    {
        Shape.Push(Tmp.Length)
        Tmp := Tmp[Tmp.MaxDimIndex]
    }
    
    Shape.Push(Tmp.Length)
    
    Return Shape
}

ListCmp(Lst1, Lst2)
{
    Lst1 := Print.ToString(Lst1)
    Lst2 := Print.ToString(Lst2)
    
    if StrCompare(Lst1, Lst2) < 0
        Return -1
    
    else if StrCompare(Lst1, Lst2) > 0
        Return 1
    
    else
        Return 0
}

Object2Map(this)
{
    Tmp := Map()
    
    For Key, Value in this.OwnProps()
        Tmp[Key] := Value
    
    Return Tmp
}

SetArrItem(this)
{
    Return SetArrItem2
}

SetArrItem2(this, Pos*)
{
    Ret := [this[Pos[1]]]
    
    Loop Pos.Length - 3
        Ret.Push(Ret[A_Index][Pos[A_Index + 1]])
    
    Ret[-1][Pos[-2]] := Pos[-1]
    
    Return this
}

使用说明:

依赖库Print用于调试以及使用Print.ToString函数。

Print源码

Class Print
{
    Static _gui := "", hwnd := 0, ctlHwnd := 0
    Static StartMakingGui := 0, locked := 1
    Static WinName := "Print Window"
    Static FloatPos := 8
    
    __New(Content, TimeStamp := true)
    {
        Print.Msg(Content, TimeStamp)
    }
    
    Static Msg(Content, TimeStamp := true)
    {
        this.makeGui()
        Content := Print.ToString(Content)
        
        If (TimeStamp) ; append timestamp + str
            Content := "[" A_Hour ":" A_Min ":" A_Sec "] " Content "`r`n"
        
        If (this.hwnd)
        {
            Lst_Content := StrSplit(Content, "`n")
            
            Loop Lst_Content.Length
            {
                this.AppendTxt(this.ctlHwnd, StrPtr(Lst_Content[A_Index]))
                this._gui["EditBox"].Value .= "`n"
            }
        }
    }
    
    Static makeGui()
    {
        If (WinExist("ahk_id " this.hwnd))
            return
        
        If (this.hwnd Or this.StartMakingGui) ; skip making the GUI
            return
        
        this.StartMakingGui := 1
        
        guiClose := ObjBindMethod(this,"gClose")
        this.guiClose := guiClose
        guiSize := ObjBindMethod(this,"gSize")
        this.guiSize := guiSize
        ctlEvent := ObjBindMethod(this,"event")
        this.ctlEvent := ctlEvent
        
        ArkDebugObj := Gui("+Resize +AlwaysOnTop", this.WinName)
        ArkDebugObj.OnEvent("close", this.guiClose)
        ArkDebugObj.OnEvent("size", this.guiSize)
        
        ArkDebugObj.SetFont("s11","Courier New")
        ctl := ArkDebugObj.Add("Button","vCopy x5 y5 Section","Copy to Clipboard").OnEvent("Click",ctlEvent)
        ctl := ArkDebugObj.Add("Button","vClear yp x+5","Clear Window").OnEvent("Click",ctlEvent)
        
        ctl := ArkDebugObj.Add("Edit","vEditBox xs y+0 w700 h500 Multi ReadOnly")
        this.ctlHwnd := ctl.hwnd, ctl := ""
        
        ArkDebugObj.Show("NA NoActivate")
        
        this.locked := 0
        this.hwnd := ArkDebugObj.hwnd
        this.locked := 1
        
        this._gui := ArkDebugObj
    }
    
    Static gClose(g)
    {
        this._gui.Destroy()
        this.hwnd := 0, this.ctlHwnd := 0
        this.StartMakingGui := 0
    }
    
    Static gSize(g, MinMax, Width, Height)
    {
        ; msgbox "in size"
        x := "", y := "", w := "", h := "", ctl := ""
        w := Width - 10, h := Height - 10 - 40
        ctl := g["EditBox"]
        ctl.GetPos(&x,&y)
        ctl.Move(x,y,w,h)
    }
    
    Static AppendTxt(hEdit, ptrText, loc:="bottom")
    {
        charLen := SendMessage(0x000E, 0, 0, , "ahk_id " hEdit)                        ;WM_GETTEXTLENGTH
        If (loc = "bottom")
            SendMessage 0x00B1, charLen, charLen, , "ahk_id " hEdit    ;EM_SETSEL
        Else If (loc = "top")
            SendMessage 0x00B1, 0, 0,, "ahk_id " hEdit
        SendMessage 0x00C2, False, ptrText, , "ahk_id " hEdit            ;EM_REPLACESEL
    }
    
    Static event(ctl,info)
    {
        If (ctl.Name = "Copy")
            A_Clipboard := ctl.gui["EditBox"].Value
        Else If (ctl.Name = "Clear")
            ctl.gui["EditBox"].Value := ""
    }
    
    Static ToString(Text)
    {
        if Type(Text) == "Array"
        {
            if Text.Length < 1
                Text.InsertAt(1, "")
            
            String_Plus := ""
            String_Text := "[" . Print.ToString(Text[1])
            
            Loop Text.Length - 1
                String_Plus .= "," . Print.ToString(Text[A_Index + 1])
            
            String_Text .= String_Plus
            String_Text .= "]"
            
            Return String_Text
        }
        
        else if Type(Text) == "List"
        {
            if Text.Length < 1
                Text.InsertAt(1, "")
            
            String_Plus := ""
            String_Text := "[" . Print.ToString(Text[0])
            
            Loop Text.Length - 1
                String_Plus .= "," . Print.ToString(Text[A_Index])
            
            String_Text .= String_Plus
            String_Text .= "]"
            
            Return String_Text
        }
        
        else if Type(Text) == "ComObjArray"
        {
            if Text.MaxIndex() < 0
            {
                Text := ComObjArray(VT_VARIANT:=12, 1)
                Text[0] := ""
            }
            
            String_Plus := ""
            String_Text := "[" . Print.ToString(Text[0])
            
            Loop Text.MaxIndex()
                String_Plus .= "," . Print.ToString(Text[A_Index])
            
            String_Text .= String_Plus
            String_Text .= "]"
            
            Return String_Text
        }
        
        else if Type(Text) == "Numpy.NDArray" || Type(Text) == "Numahk.NDArray"
        {
            if Text.array.Length < 1
                Text.array.InsertAt(1, "")
            
            String_Plus := ""
            String_Text := "[" . Print.ToString(Text.array[0])
            
            Loop Text.array.Length - 1
                String_Plus .= "," . Print.ToString(Text.array[A_Index])
            
            String_Text .= String_Plus
            String_Text .= "]"
            
            Return String_Text
        }
        
        else if Type(Text) == "Set"
            Return "Set(" Print.ToString(Text.list) ")"
        
        else if Type(Text) == "Map" || Type(Text) == "Dict"
        {
            String_Text := "{"
            
            For i, Value in Text
                String_Text .= Print.ToString(i) . ":" . Print.ToString(Value) . ","
            
            if SubStr(String_Text, -1) !== "{"
                String_Text := SubStr(String_Text, 1, StrLen(String_Text) - 1)
            
            String_Text .= "}"
            
            Return String_Text
        }
        
        else if Type(Text) == "Pandas.DataFrame"
        {
            String_Text := "`t"
            
            For i in Text.Columns
                String_Text .= Print.ToString(i) "`t"
            
            String_Text := SubStr(String_Text, 1, StrLen(String_Text) - 1)
            String_Text .= "`n"
            
            Loop Text.Index.Length
            {
                index := A_Index - 1
                String_Text .= Print.ToString(Text.Index[index]) "`t"
                
                Loop Text.Data.array.Length
                    String_Text .= Print.ToString(Text.Data.array[A_Index - 1][index]) "`t"
                
                String_Text := SubStr(String_Text, 1, StrLen(String_Text) - 1)
                String_Text .= "`n"
            }
            
            String_Text := SubStr(String_Text, 1, StrLen(String_Text) - 1)
            
            Return String_Text
        }
        
        else if Type(Text) == "Integer" || Type(Text) == "String"
            Return String(Text)
        
        else if Type(Text) == "Float"
            Return Round(Text, this.FloatPos)
        
        else if Type(Text) == "Object"
        {
            String_Text := "{"
            
            For i, Value in Text.OwnProps()
                String_Text .= Print.ToString(i) . ":" . Print.ToString(Value) . ","
            
            if SubStr(String_Text, -1) !== "{"
                String_Text := SubStr(String_Text, 1, StrLen(String_Text) - 1)
            
            String_Text .= "}"
            
            Return String_Text
        }
        
        else if Type(Text) == "ListNode"
        {
            String_Text := "{val:"
            String_Text .= Print.ToString(Text.val)
            String_Text .= "}"
            
            if Text.next
            {
                String_Text .= "->"
                String_Text .= Print.ToString(Text.next)
            }
            
            Return String_Text
        }
        
        else if Type(Text) == "Cv_Mat_Object"
        {
            String_Text := "Channels: " Text.Channels
            String_Text .= "`nData: " Text.Data
            String_Text .= "`nDepth: " Text.Depth
            String_Text .= "`nShape: " Print.ToString([Text.Rows, Text.Cols, Text.Channels])
            String_Text .= "`nSize: " Text.Size
            String_Text .= "`nStep1: " Text.Step1
            String_Text .= "`nTotal: " Text.Total
            String_Text .= "`nType: " Text.Type
            String_Text .= "`nCols: " Text.MAT.Cols
            String_Text .= "`nDims: " Text.MAT.Dims
            String_Text .= "`nRows: " Text.MAT.Rows
            
            Return String_Text
        }
        
        else if Type(Text) == "CV2.MAT"
        {
            Return Print.ToString(Text.MAT)
        }
        
        else if Type(Text) == "Func"
        {
            String_Text := "Name: " Text.Name
            String_Text .= "`nIsBuiltIn: " Text.IsBuiltIn
            String_Text .= "`nIsVariadic: " Text.IsVariadic
            String_Text .= "`nMinParams: " Text.MinParams
            String_Text .= "`nMaxParams: " Text.MaxParams
            
            Return String_Text
        }
        
        else if Type(Text) == "Class"
        {
            String_Text := ""
            
            For item, value in Text.Prototype.OwnProps()
                String_Text .= item ": " value "`n"
            
            Return SubStr(String_Text, 1, StrLen(String_Text) - 1)
        }
        
        else if Type(Text) == "Gui"
        {
            String_Text := "BackColor: " Text.BackColor
            String_Text .= "`nFocusedCtrl: " Text.FocusedCtrl
            String_Text .= "`nHwnd: " Text.Hwnd
            String_Text .= "`nMarginX: " Text.MarginX
            String_Text .= "`nMarginY: " Text.MarginY
            String_Text .= "`nMenuBar: " Text.MenuBar
            String_Text .= "`nName: " Text.Name
            String_Text .= "`nTitle: " Text.Title
            String_Text .= "`nItem: `n{`n"
            
            For Hwnd, GuiCtrlObj in Text
            {
                String_Text .= "  Control #" A_Index "[Hwnd: " Hwnd ",ClassNN: " GuiCtrlObj.ClassNN "]`n"
            }
            
            String_Text .= "}"
            
            Return String_Text
        }
        
        else
            Return "#Type: " Type(Text) "#"
    }
}

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

用ahk搞播放器按键增强的思路

2022-9-6 8:41:31

其他

vscode便携制作ahk,py编辑傻瓜版

2022-9-7 8:22:11

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
有新私信 私信列表
搜索