1 Star 3 Fork 2

WinH/Excel-VBA-Dicts

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Lists.bas 30.00 KB
一键复制 编辑 原始数据 按行查看 历史
WinH 提交于 2019-06-28 23:12 . Update Lists.bas
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'@desc Util Class Lists
'@author Qiou Yang
'@license MIT
'@lastUpdate 28.06.2019
' remove the redundant functions,
' remove destructor which may cause bug in 64 bit env,
' add support for Collection
'@TODO optional params
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Option Explicit
Private pArr() As Variant ' the underlying array object
Private pMaxLen As Integer ' the maximal length of array object
Private pLen As Integer ' the length of current List Object
Private pRes ' res for the callback map/reduce/filter
Public Property Let callback(res)
If IsObject(res) Then
Set pRes = res
Else
pRes = res
End If
End Property
Public Property Get callback()
If IsObject(pRes) Then
Set callback = pRes
Else
callback = pRes
End If
End Property
Public Property Get length() As Integer
length = pLen
End Property
Public Function init() As Lists
pMaxLen = 20
pLen = 0
ReDim pArr(0 To pMaxLen - 1)
Set init = Me
End Function
Public Function toDict() As Dicts
Dim res As New Dicts
Dim i
For i = 0 To pLen - 1
res.dict.add Me.getVal(i), i
Next i
Set toDict = res
Set res = Nothing
End Function
Public Function toMap() As Dicts
Dim res As New Dicts
Dim i
For i = 0 To pLen - 1
res.dict.add i, Me.getVal(i)
Next i
Set toMap = res
Set res = Nothing
End Function
Public Function clear() As Lists
Me.init
End Function
Private Sub Class_Initialize()
Me.init
End Sub
Private Sub check()
If pLen > pMaxLen * 0.75 Then
pMaxLen = Int(pMaxLen * 1.5)
ReDim Preserve pArr(0 To pMaxLen - 1)
End If
End Sub
Private Sub override(ByRef list As Lists)
pLen = list.length
pArr = list.toArray
pMaxLen = UBound(pArr) + 1
End Sub
Public Function isEmptyList() As Boolean
isEmptyList = True
Dim i
For i = 0 To pLen - 1
If Not isEmpty(pArr(i)) Then
isEmptyList = False
Exit For
End If
Next i
End Function
Private Function isInstance(obj, ByVal sign) As Boolean
isInstance = TypeName(obj) = sign
End Function
Public Function isLists(testObj As Variant) As Boolean
isLists = TypeName(testObj) = "Lists"
End Function
'in case of 1 * N or N * 1 matrix, return 1-dimensional array
Public Function fromRng(ByRef rng As Range, Optional ByVal orientation As String = "v") As Lists
Dim res As New Lists
Dim rowNum As Integer
rowNum = rng.Rows.Count
Dim colNum As Integer
colNum = rng.Columns.Count
Dim i
If rowNum = 1 Or colNum = 1 Then
res.addAll rng
Else
Dim tmp As New Lists
For i = 1 To rowNum
res.add tmp.fromRng(rng.Rows(i))
Next i
End If
If orientation = "h" Or orientation = "H" Then
If rowNum = 1 Or colNum = 1 Then
Dim res1 As New Lists
Dim tmp1 As New Lists
For i = 0 To res.length - 1
tmp1.init
res1.add tmp1.add(res.getVal(i), False)
Set tmp1 = Nothing
Next i
Set res = res1
Set res1 = Nothing
Else
Set res = res.zipMe
End If
End If
Set fromRng = res
End Function
Public Function toRng(ByRef rng As Range)
If Me.length > 0 Then
Dim y
y = pLen
If y = 1 Then
rng.Resize(1, pArr(0).length).value = Me.toArray
Else
Dim lenArr As New Lists
Dim i
For i = 0 To pLen - 1
If isInstance(pArr(i), "Lists") Then
lenArr.add pArr(i).length
Else
lenArr.add 1
End If
Next i
Dim maxLen As Integer
maxLen = lenArr.max_
rng.Resize(1, maxLen).Cells.clear
For i = 0 To pLen - 1
If isInstance(pArr(i), "Lists") Then
rng.offSet(i, 0).Resize(1, pArr(i).length).value = pArr(i).toArray
Else
rng.offSet(i, 0).value = pArr(i)
End If
Next i
End If
End If
End Function
Public Function fromString(ByVal str As String) As Lists
Dim l As New Lists
Dim i As Integer
For i = 1 To Len(str)
l.add Mid(str, i, 1)
Next i
Set fromString = l
Set l = Nothing
End Function
Public Function join(ByVal delimiter As String) As String
join = Strings.join(Me.toArray, delimiter)
End Function
Public Function fromArray(arr, Optional ByVal iter As Boolean = True) As Lists
Dim l As New Lists
If iter Then
Dim i
For Each i In arr
If IsArray(i) Or TypeName(i) = "Collection" Then
l.add fromArray(i)
Else
l.add i
End If
Next i
Set fromArray = l
Else
Set fromArray = l.addAll(arr)
End If
Set l = Nothing
End Function
Private Function serial(ByVal start As Long, ByVal ending As Long, Optional ByVal steps As Long = 1) As Variant
Dim res()
Dim cnt As Long
cnt = -1
Dim i As Long
For i = start To ending Step steps
cnt = cnt + 1
Next i
If cnt > -1 Then
ReDim res(0 To cnt)
Dim cnt1 As Long
cnt1 = 0
For i = start To ending Step steps
res(cnt1) = i
cnt1 = cnt1 + 1
Next i
End If
serial = res
End Function
Public Function fromSerial(ByVal start As Long, ByVal ending As Long, Optional ByVal steps As Long = 1) As Lists
Me.clear
Set fromSerial = Me.addAll(serial(start, ending, steps))
End Function
Public Function ones(ByVal n As Long) As Lists
Set ones = Me.fromSerial(1, n).map("_/({i}+1)")
End Function
Public Function add(ele, Optional ByVal keepOldElements As Boolean = True) As Lists
Call check
If Not keepOldElements Then
Me.clear
End If
If IsObject(ele) Then
Set pArr(pLen) = ele
Else
pArr(pLen) = ele
End If
pLen = pLen + 1
Set add = Me
End Function
Public Function Remove(ByVal ele) As Lists
If Me.contains(ele) Then
Set Remove = Me.removeAt(Me.indexOf(ele))
Else
Set Remove = Me
End If
End Function
Public Function removeAt(ByVal index As Integer) As Lists
Dim res As New Lists
Set res = Me.slice(, index).addList(Me.slice(index + 1))
Call override(res)
Set removeAt = Me
End Function
Public Function addAt(ByVal ele, ByVal index As Integer) As Lists
Dim res As Lists
Set res = Me.slice(, index).add(ele).addList(Me.slice(index))
Call override(res)
Set addAt = Me
End Function
Public Function addAllAt(ByVal eles, ByVal index As Integer) As Lists
Dim res As Lists
Set res = Me.slice(, index).addAll(eles).addList(Me.slice(index))
Call override(res)
Set addAllAt = Me
End Function
Public Function replaceAllAt(ByVal eles, ByVal index As Integer) As Lists
Dim res As Lists
Set res = Me.slice(, index).addAll(eles).addList(Me.slice(index + 1))
Call override(res)
Set replaceAllAt = Me
End Function
Public Function unshift(ParamArray l() As Variant) As Lists
Set unshift = Me.addAllAt(l, 0)
End Function
Public Function push(ParamArray l() As Variant) As Lists
Set push = Me.addAllAt(l, Me.length)
End Function
Public Function permutation() As Lists
Dim res As New Lists
If Me.length <= 1 Then
res.add Me
Else
Dim i, j
Dim tmp As Lists
Dim ele
For i = 0 To Me.length - 1
Set tmp = Me.copy.removeAt(i).permutation
For j = 0 To tmp.length - 1
res.add tmp.getVal(j).unshift(Me.getVal(i))
Next j
Next i
End If
Set permutation = res
End Function
Public Function addAll(arr, Optional ByVal keepOldElements As Boolean = True) As Lists
If Not keepOldElements Then
Me.clear
End If
Dim i
If isInstance(arr, "Lists") Then
For i = 0 To arr.length - 1
Me.add arr.getVal(i)
Next i
ElseIf TypeName(arr) = "Range" Then
For Each i In arr.value
Me.add i
Next i
ElseIf IsArray(arr) Then
If Not isArrayEmpty(arr) Then
For Each i In arr
Me.add i
Next i
End If
Else
Me.add arr
End If
Set addAll = Me
End Function
Private Function isArrayEmpty(arr) As Boolean
On Error GoTo hdl
Dim res As Boolean
res = True
Dim tmp
If IsArray(arr) Then
tmp = arr(LBound(arr))
End If
hdl:
If Err.Number = 0 Then
res = False
End If
isArrayEmpty = res
End Function
Public Function addList(ByRef l As Lists) As Lists
If l.length > 0 Then
Me.addAll (l.toArray)
End If
Set addList = Me
End Function
Public Function of(ParamArray l() As Variant) As Lists
Dim tmp
Dim res As New Lists
For Each tmp In l
res.add tmp
Next tmp
Set of = res
Set res = Nothing
End Function
Public Function zip(ParamArray l() As Variant) As Lists
Dim res As New Lists
Dim targLen As Integer ' the length of res
targLen = pLen
Dim tmp
Dim i
For Each tmp In l
If targLen > tmp.length Then
targLen = tmp.length
End If
Next tmp
For i = 0 To targLen - 1
Dim tmpList As New Lists
tmpList.init
tmpList.add pArr(i)
For Each tmp In l
tmpList.add tmp.getVal(i)
Next tmp
res.add tmpList
Set tmpList = Nothing
Next i
Set zip = res
End Function
' zip the Lists within the Lists
Public Function zipMe() As Lists
If pLen = 0 Then
Set zipMe = Me
ElseIf pLen = 1 Then
If Me.isLists(Me.getVal(0)) Then
Dim k
Dim l As New Lists
Dim tmp1 As New Lists
For k = 0 To Me.getVal(0).length - 1
l.add tmp1.add(Me.getVal(0).getVal(k))
Set tmp1 = Nothing
Next k
Set zipMe = l
Set l = Nothing
Set tmp1 = Nothing
Else
Set zipMe = Me
End If
Else
Dim i
Dim j
Dim res As New Lists
Dim lenArr As New Lists
lenArr.init
For i = 0 To pLen - 1
lenArr.add pArr(i).length
Next i
For j = 0 To lenArr.min_ - 1
Dim tmp As New Lists
tmp.init
For i = 0 To pLen - 1
tmp.add pArr(i).getVal(j)
Next i
res.add tmp
Set tmp = Nothing
Next j
Set zipMe = res
End If
End Function
Public Function getVal(ByVal index As Integer, Optional ByVal index2)
If index >= pLen Or index < 0 Then
Err.Raise 8888, , "ArrayIndexOutOfBoundException"
End If
If Not IsObject(pArr(index)) Then
getVal = pArr(index)
Else
If IsMissing(index2) Then
Set getVal = pArr(index)
Else
If IsObject(pArr(index).getVal(index2)) Then
Set getVal = pArr(index).getVal(index2)
Else
getVal = pArr(index).getVal(index2)
End If
End If
End If
End Function
Public Function setVal(ByVal index As Integer, ByVal ele As Variant) As Lists
If index >= pLen Or index < 0 Then
Err.Raise 8888, , "ArrayIndexOutOfBoundException"
End If
If IsObject(ele) Then
Set pArr(index) = ele
Else
pArr(index) = ele
End If
Set setVal = Me
End Function
Public Function indexOf(ByVal ele) As Integer
Dim i As Integer
Dim hasFound As Boolean
hasFound = False
For i = 0 To pLen
If pArr(i) = ele Then
hasFound = True
Exit For
End If
Next i
If hasFound Then
indexOf = i
Else
indexOf = -1
End If
End Function
' l the length of the subgroups
' offSet from the first beginnig to next beginning
' sobgroupBy(2,3) [1,2,3,4,5] -> [[1, 2], [4, 5] ] [[i0, i1, ...i(l-1)], [i(0 + offset), i(1 + offset), ... i(l-1+offset)]]
Public Function subgroupBy(l As Long, offSet As Long) As Lists
Dim res As New Lists
Dim tmp As Lists
Dim cnt As Long
cnt = 0
Do While True
Set tmp = Me.slice(min__(offSet * cnt, Me.length), min__(l + offSet * cnt, Me.length))
If tmp.length = 0 Then
Exit Do
End If
res.add tmp
cnt = cnt + 1
Loop
Set subgroupBy = res
Set res = Nothing
Set tmp = Nothing
End Function
Private Function min__(a, b) As Variant
min__ = IIf(a > b, b, a)
End Function
Private Function max__(a, b) As Variant
max__ = IIf(a > b, a, b)
End Function
Public Function contains(ByVal ele) As Boolean
contains = Me.indexOf(ele) > -1
End Function
Public Function min_() As Variant
Dim res
res = pArr(0)
Dim i As Integer
For i = 1 To pLen - 1
If pArr(i) < res Then
res = pArr(i)
End If
Next i
min_ = res
End Function
Public Function max_() As Variant
Dim res
res = pArr(0)
Dim i As Integer
For i = 1 To pLen - 1
If pArr(i) > res Then
res = pArr(i)
End If
Next i
max_ = res
End Function
Public Function avg() As Double
avg = Me.reduce("?+_", 0) / pLen
End Function
Public Function containsAll(ByVal arr) As Boolean
Dim res As Boolean
res = True
Dim i
For Each i In arr
If Not Me.contains(i) Then
res = False
Exit For
Else
Next i
containsAll = res
End Function
Public Function subList(ByVal fromIndex As Integer, ByVal toIndex As Integer) As Lists
Set subList = Me.slice(fromIndex, toIndex, 1)
End Function
Public Function every(ByVal judgement As String, Optional ByVal placeholder As String = "_", Optional ByVal idx As String = "{i}", Optional ByVal replaceDecimalPoint As Boolean = True) As Boolean
Dim res As Boolean
res = True
Dim i
Dim cnt As Long
cnt = 0
If replaceDecimalPoint Then
For Each i In Me.toArray
If Not Application.Evaluate(Replace(Replace(judgement, placeholder, Replace("" & i, ",", ".")), idx, cnt)) Then
res = False
Exit For
End If
cnt = cnt + 1
Next i
Else
For Each i In Me.toArray
If Not Application.Evaluate(Replace(Replace(judgement, placeholder, "" & i), idx, cnt)) Then
res = False
Exit For
End If
cnt = cnt + 1
Next i
End If
every = res
End Function
Public Function some(ByVal judgement As String, Optional ByVal placeholder As String = "_", Optional ByVal idx As String = "{i}", Optional ByVal replaceDecimalPoint As Boolean = True) As Boolean
Dim res As Boolean
res = False
Dim i
Dim cnt As Long
cnt = 0
If replaceDecimalPoint Then
For Each i In Me.toArray
If Application.Evaluate(Replace(Replace(judgement, placeholder, Replace("" & i, ",", ".")), idx, cnt)) Then
res = True
Exit For
End If
cnt = cnt + 1
Next i
Else
For Each i In Me.toArray
If Application.Evaluate(Replace(Replace(judgement, placeholder, "" & i), idx, cnt)) Then
res = True
Exit For
End If
Next i
cnt = cnt + 1
End If
some = res
End Function
''''''''''''
'@param operation: string to be evaluated, e.g. _*2 will be interpreated as ele * 2
' placeholder: placeholder to be replaced by the value
' idx: index of the element
' replaceDecimalPoint: whether the Germany Decimal Point should be replace by "."
''''''''''''
Public Function map(ByVal operation As String, Optional ByVal placeholder As String = "_", Optional ByVal idx As String = "{i}", Optional ByVal replaceDecimalPoint As Boolean = True, Optional ByVal setNullValTo = 0) As Lists
Dim res As New Lists
Dim i
Dim cnt As Long
cnt = 0
If replaceDecimalPoint Then
For Each i In Me.toArray
i = IIf(isEmpty(i), setNullValTo, i)
res.add (Application.Evaluate(Replace(Replace(operation, placeholder, Replace("" & i, ",", ".")), idx, cnt & "")))
cnt = cnt + 1
Next i
Else
For Each i In Me.toArray
i = IIf(isEmpty(i), setNullValTo, i)
res.add (Application.Evaluate(Replace(Replace(operation, placeholder, "" & i), idx, cnt & "")))
cnt = cnt + 1
Next i
End If
Set map = res
Set res = Nothing
End Function
' signature of callback should be,
' sub callback(byref l as Lists, e, optional byval i as Long)
' update Me.modification
Public Function mapX(Optional ByVal callback As String = "callback") As Lists
Dim res As New Lists
Dim i
For i = 0 To Me.length - 1
Application.Run callback, Me, Me.getVal(i), i
res.add pRes
Next i
Set mapX = res
Set res = Nothing
End Function
' first reduce then map
Public Function mapList(ByVal operation As String, ByVal reduceOp As String, Optional ByVal placeholder As String = "_", Optional ByVal idx As String = "{i}", Optional ByVal replaceDecimalPoint As Boolean = True, Optional ByVal initialVal = 1, Optional ByVal placeholderInitialVal As String = "?") As Lists
Dim res As New Lists
Dim tmp As New Lists
Dim i
Dim cnt As Long
cnt = 0
If replaceDecimalPoint Then
For Each i In Me.toArray
i = tmp.addAll(i).reduce(reduceOp, initialVal, placeholder, placeholderInitialVal, idx, replaceDecimalPoint)
res.add (Application.Evaluate(Replace(Replace(operation, placeholder, Replace("" & i, ",", ".")), idx, cnt & "")))
cnt = cnt + 1
Next i
Else
For Each i In Me.toArray
i = tmp.addAll(i).reduce(reduceOp, initialVal, placeholder, placeholderInitialVal, idx, replaceDecimalPoint)
res.add (Application.Evaluate(Replace(Replace(operation, placeholder, "" & i), idx, cnt & "")))
cnt = cnt + 1
Next i
End If
Set mapList = res
Set tmp = Nothing
End Function
''''''''''''
'@param judgement: string to be evaluated and return Boolean, e.g. _>2 will be interpreated as ele > 2
' placeholder: placeholder to be replaced by the value
' replaceDecimalPoint: whether the Germany Decimal Point should be replace by "."
''''''''''''
Public Function filter(ByVal judgement As String, Optional ByVal placeholder As String = "_", Optional ByVal idx As String = "{i}", Optional ByVal replaceDecimalPoint As Boolean = True, Optional ByVal setNullValTo = 0) As Lists
Dim res As New Lists
Dim i
Dim cnt As Long
cnt = 0
If replaceDecimalPoint Then
For Each i In Me.toArray
i = IIf(isEmpty(i), setNullValTo, i)
If Application.Evaluate(Replace(Replace(judgement, placeholder, Replace("" & i, ",", ".")), idx, cnt)) Then
res.add i
End If
cnt = cnt + 1
Next i
Else
For Each i In Me.toArray
i = IIf(isEmpty(i), setNullValTo, i)
If Application.Evaluate(Replace(Replace(judgement, placeholder, "" & i), idx, cnt)) Then
res.add i
End If
cnt = cnt + 1
Next i
End If
Set filter = res
End Function
' signature of callback should be,
' sub callback_judgement(byref l as Lists, e, optional byval i as Long)
' update Me.callback
Public Function filterX(Optional ByVal callback As String = "callback") As Lists
Dim res As New Lists
Dim i
For i = 0 To Me.length - 1
Application.Run callback, Me, Me.getVal(i), i
If pRes Then
res.add Me.getVal(i)
End If
Next i
Set filterX = res
Set res = Nothing
End Function
Public Function take(ByVal n As Long) As Lists
n = IIf(n >= 0, n, Me.length + n)
Set take = Me.slice(0, n, 1)
End Function
Public Function drop(ByVal n As Long) As Lists
n = IIf(n >= 0, n, Me.length + n)
Set drop = Me.slice(n, , 1)
End Function
Public Function dropLast(ByVal n As Long) As Lists
Set dropLast = take(Me.length - n)
End Function
Public Function filterIndex(indexArr As Variant) As Lists
Dim i
Dim res As New Lists
For Each i In xToArray(indexArr)
res.add Me.getVal(i)
Next i
Set filterIndex = res
Set res = Nothing
End Function
Public Function filterWith(arr As Variant) As Lists
Dim i
Dim cnt As Long
cnt = 0
Dim res As New Lists
For Each i In xToArray(arr)
If i Then
res.add Me.getVal(cnt)
End If
cnt = cnt + 1
If cnt = Me.length Then
Exit For
End If
Next i
Set filterWith = res
End Function
Public Function filterReg(ByRef reg As Object) As Lists
Set filterReg = Me.filterWith(Me.judgeReg(reg))
End Function
'@desc map to boolean array based on reg
Public Function judgeReg(ByVal reg As Object) As Lists
Dim i As Long
Dim res As New Lists
For i = 0 To Me.length - 1
res.add reg.Test(Me.getVal(i))
Next i
Set judgeReg = res
Set res = Nothing
End Function
'@desc RegExp should contain at least one group, if matched the first group will be mapped to the list, otherwise keep the original value
Public Function mapReg(ByVal reg As Object) As Lists
Dim i As Long
Dim res As New Lists
For i = 0 To Me.length - 1
If reg.Test(Me.getVal(i)) Then
res.add reg.Execute(Me.getVal(i))(0).submatches(0)
Else
res.add Me.getVal(i)
End If
Next i
Set mapReg = res
Set res = Nothing
End Function
Public Function nullVal(Optional setValTo As Variant) As Lists
Dim res As New Lists
Dim i
'setValTo missing, left out empty value
If IsMissing(setValTo) Then
For i = 0 To Me.length - 1
If Not isEmpty(Me.getVal(i)) Then
res.add Me.getVal(i)
End If
Next i
Else
For i = 0 To Me.length - 1
res.add IIf(isEmpty(Me.getVal(i)), setValTo, Me.getVal(i))
Next i
End If
Set nullVal = res
Set res = Nothing
End Function
Public Function reduce(ByVal operation As String, ByVal initialVal As Variant, Optional ByVal placeholder As String = "_", Optional ByVal placeholderInitialVal As String = "?", Optional ByVal idx As String = "{i}", Optional ByVal replaceDecimalPoint As Boolean = True) As Variant
Dim res
Dim i
res = initialVal
Dim cnt As Long
cnt = 0
If replaceDecimalPoint Then
For Each i In Me.toArray
res = Application.Evaluate(Replace(Replace(Replace(operation, placeholder, Replace("" & i, ",", ".")), placeholderInitialVal, Replace("" & res, ",", ".")), idx, cnt))
cnt = cnt + 1
Next i
Else
For Each i In Me.toArray
res = Application.Evaluate(Replace(Replace(Replace(operation, placeholder, "" & i), placeholderInitialVal, "" & res), idx, cnt))
cnt = cnt + 1
Next i
End If
reduce = res
End Function
' signature of callback should be,
' sub callback(byref l as Lists, e, optional byval i as Long)
' update Me.modification as acc
Public Function reduceX(Optional ByVal callback As String = "callback", Optional initVal = 0)
Dim i
Me.callback = initVal
For i = 0 To Me.length - 1
Application.Run callback, Me, Me.getVal(i), i
Next i
If IsObject(pRes) Then
Set reduceX = pRes
Else
reduceX = pRes
End If
End Function
Public Function reduceRight(ByVal operation As String, ByVal initialVal As Variant, Optional ByVal placeholder As String = "_", Optional ByVal placeholderInitialVal As String = "?", Optional ByVal idx As String = "{i}", Optional ByVal replaceDecimalPoint As Boolean = True) As Variant
reduceRight = Me.reverse().reduce(operation, initialVal, placeholder, placeholderInitialVal, idx, replaceDecimalPoint)
End Function
Public Function product(ByVal operation As String, ByRef list2 As Lists, Optional ByVal placeholder As String = "_", Optional ByVal placeholderOther As String = "?", Optional ByVal idx As String = "{i}", Optional ByVal replaceDecimalPoint As Boolean = True) As Lists
Dim res As New Lists
Dim i As Integer
Dim cnt As Long
cnt = 0
Dim targLen As Integer
targLen = min__(pLen, list2.length) - 1
If replaceDecimalPoint Then
For i = 0 To targLen
res.add Application.Evaluate(Replace(Replace(Replace(operation, placeholder, Replace("" & pArr(i), ",", ".")), placeholderOther, Replace("" & list2.getVal(i), ",", ".")), idx, cnt))
cnt = cnt + 1
Next i
Else
For i = 0 To targLen
res.add Application.Evaluate(Replace(Replace(Replace(operation, placeholder, "" & pArr(i)), placeholderOther, "" & list2.getVal(i)), idx, cnt))
cnt = cnt + 1
Next i
End If
Set product = res
End Function
Public Function slice(Optional ByVal fromIndex, Optional ByVal toIndex, Optional ByVal step) As Lists
Dim res As New Lists
If IsMissing(fromIndex) Then
fromIndex = 0
End If
If IsMissing(toIndex) Then
toIndex = pLen
End If
If IsMissing(step) Then
step = 1
End If
If fromIndex < 0 Then
fromIndex = pLen + fromIndex
End If
If toIndex < 0 Then
toIndex = pLen + toIndex
End If
If fromIndex <> toIndex Then
Dim i As Integer
If step > 0 Then
For i = fromIndex To toIndex - 1 Step step
res.add pArr(i)
Next i
Else
For i = toIndex - 1 To fromIndex Step step
res.add pArr(i)
Next i
End If
End If
Set slice = res
End Function
Private Function xToArray(x As Variant) As Variant
If IsArray(x) Then
xToArray = x
ElseIf isInstance(x, "Lists") Then
xToArray = x.toArray
Else
xToArray = Array(x)
End If
End Function
Public Function toArray() As Variant
Dim arr()
If pLen > 0 Then
ReDim arr(0 To pLen - 1)
Dim i As Integer
For i = 0 To pLen - 1
If Not IsObject(pArr(i)) Then
arr(i) = pArr(i)
Else
If Me.isLists(pArr(i)) Then
arr(i) = pArr(i).toArray()
Else
Set arr(i) = pArr(i)
End If
End If
Next i
Else
arr = Array()
End If
toArray = arr
End Function
Public Function toString()
Dim d As New Dicts
toString = d.x_toString(Me)
Set d = Nothing
End Function
Public Function isInstanceOf(testObj, typeArr) As Boolean
Dim s As String
s = TypeName(testObj)
If TypeName(typeArr) = "String" Then
isInstanceOf = s = typeArr
ElseIf IsArray(typeArr) Then
Dim k
Dim res As Boolean
res = False
For Each k In typeArr
If s = k Then
res = True
Exit For
End If
Next k
isInstanceOf = res
ElseIf isInstanceOf(typeArr, "Lists") Then
isInstanceOf = isInstanceOf(testObj, typeArr.toArray)
Else
Err.Raise 9980, , "ParameterTypeErrorException: typeArr should be either String, Array or Lists"
End If
End Function
Public Function sort(Optional ByVal isAscending As Boolean = True) As Lists
Dim res As New Lists
Dim arr
arr = Me.toArray
Call QuickSort(arr, 0, pLen - 1)
res.addAll arr
If isAscending Then
Set res = res.reverse
End If
Call override(res)
Set sort = Me
End Function
Public Function reverse() As Lists
Set reverse = Me.slice(, , -1)
End Function
Public Function p()
Debug.Print Me.toString
End Function
Public Function unique() As Lists
Dim tmp As Object
Set tmp = New TreeMaps
Dim k
For Each k In Me.toArray
tmp(k) = 1
Next k
Me.clear
Set unique = Me.addAll(tmp.Keys)
Set tmp = Nothing
End Function
Public Function copy() As Lists
Dim res As New Lists
res.addAll (Me.toArray)
Set copy = res
End Function
Private Sub QuickSort(vArray As Variant, ByVal inLow As Integer, ByVal inHi As Integer)
Dim pivot As Variant
Dim tmpSwap As Variant
Dim tmpLow As Integer
Dim tmpHi As Integer
tmpLow = inLow
tmpHi = inHi
pivot = vArray((inLow + inHi) \ 2)
While (tmpLow <= tmpHi)
While (vArray(tmpLow) > pivot And tmpLow < inHi)
tmpLow = tmpLow + 1
Wend
While (pivot > vArray(tmpHi) And tmpHi > inLow)
tmpHi = tmpHi - 1
Wend
If (tmpLow <= tmpHi) Then
tmpSwap = vArray(tmpLow)
vArray(tmpLow) = vArray(tmpHi)
vArray(tmpHi) = tmpSwap
tmpLow = tmpLow + 1
tmpHi = tmpHi - 1
End If
Wend
If (inLow < tmpHi) Then QuickSort vArray, inLow, tmpHi
If (tmpLow < inHi) Then QuickSort vArray, tmpLow, inHi
End Sub
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Visual Basic
1
https://gitee.com/sgfxq/Excel-VBA-Dicts.git
git@gitee.com:sgfxq/Excel-VBA-Dicts.git
sgfxq
Excel-VBA-Dicts
Excel-VBA-Dicts
master

搜索帮助

D67c1975 1850385 1daf7b77 1850385