Skip to content

Instantly share code, notes, and snippets.

@BanditTech
Created July 8, 2021 07:34
Show Gist options
  • Save BanditTech/cccbdfa9d0287db73c94a1551761fc99 to your computer and use it in GitHub Desktop.
Save BanditTech/cccbdfa9d0287db73c94a1551761fc99 to your computer and use it in GitHub Desktop.
CLASS_SortByNum.ahk
Class SortByNum {
__New(sortlist,maxOver:=14,min:=40){
; Initiate values, get the total number of potential groups
This.Excess := A.reverse(A.sortBy(sortlist,"Q"))
This.Min := min
This.Max := This.Min + maxOver
This.MaxOver := maxOver
This.TotalQ := This.GetQ(This.Excess)
This.TotalNum := This.Excess.Count()
This.Mean := Floor(A.meanBy(This.Excess,"Q"))
; Find the optimum starting number of groups, then create them
This.GetGroupNum()
This.BuildSortGroups()
; Unload some processing by First Fit
This.FillBinsFirstFit()
This.FillBinsFirstFit()
; Try to intelligently fill the remainder
This.FillBinsMulti(2) ; 2 layers deep to avoid strain on larger list
; Then try to reduce the overQ if any possible swap is available
; This.SwapForBetter()
This.BreakDownGroups()
This.SwapForBetter()
; Now we check for any remaining possible groups
This.CheckForFilledGroups()
This.BreakDownGroups()
This.SwapForBetter()
This.CheckForFilledGroups()
; With all groups hopefully filled, we destroy any below min
This.BreakDownGroups()
This.ReSort()
This.EndCounts := This.GetCounts()
This.ExcessQ := This.GetQ(This.Excess)
This.FinalMessage()
Return This.SortGroups
}
FinalMessage(){
txt := ""
For k, bin in This.SortGroups {
txt .= "<" This.GetQ(bin) ">"
for kk, vv in bin
txt .= " " vv.Q
txt .= "`n"
}
txt .= "Excess:" This.ExcessQ " Count:" This.Excess.Count() "`n"
For k, v in This.Excess {
txt .= v.Q " "
}
MsgBox % txt
}
SwapForBetter(){
While (Results := This.MultiSwap() ) {
binNum := Results.1.1
binKey := Results.1.2
binKey2 := Results.1.3
key := Results.2.1
fetch := This.SortGroups[binNum][binKey]
fetch2 := This.SortGroups[binNum][binKey2]
replace := This.Excess[key]
This.SortGroups[binNum].RemoveAt(binKey2)
This.SortGroups[binNum].RemoveAt(binKey)
This.SortGroups[binNum].Push(replace)
This.Excess.RemoveAt(key)
This.Excess.Push(fetch)
This.Excess.Push(fetch2)
; This.ReSort()
}
While (Results := This.Swap() ) {
binNum := Results.1.1
binKey := Results.1.2
key1 := Results.2.1
key2 := Results.2.2
fetch := This.SortGroups[binNum][binKey]
replace := This.Excess[key1]
If key2 {
replace2 := This.Excess[key2]
This.SortGroups[binNum].Push(replace2)
}
This.SortGroups[binNum].RemoveAt(binKey)
This.SortGroups[binNum].Push(replace)
If key2
This.Excess.RemoveAt(key2)
This.Excess.RemoveAt(key1)
This.Excess.Push(fetch)
; This.ReSort()
}
}
Swap(){
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ <= This.Min)
Continue
overQ := groupQ - This.Min
For binKey, binObj in bin {
; Going through each bin, finding replacements to lower overQ
For key1, obj1 in This.Excess {
newQ := groupQ - binObj.Q + obj1.Q
If (newQ >= This.Min && newQ - This.Min < overQ)
Return [[binNum,binKey],[key1]]
Else {
For key2, obj2 in This.Excess {
If (key1 = key2)
Continue 1
newQ := groupQ - binObj.Q + obj1.Q + obj2.Q
If (newQ >= This.Min && newQ - This.Min < overQ)
Return [[binNum,binKey],[key1,key2]]
}
}
}
}
}
Return False
}
MultiSwap(){
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ <= This.Min)
Continue
overQ := groupQ - This.Min
For binKey, binObj in bin {
; Going through each bin, finding replacements to lower overQ
For binKey2, binObj2 in bin {
If (binKey2 = binKey)
Continue
For key, obj in This.Excess {
newQ := groupQ - binObj.Q - binObj2.Q + obj.Q
If (newQ >= This.Min && newQ - This.Min < overQ){
Return [[binNum,binKey,binKey2],[key]]
}
}
}
}
}
Return False
}
BreakDownGroups(){
cleanup := []
For binNum, bin in This.SortGroups {
If (This.GetQ(bin) < This.Min)
cleanup.Push(binNum)
}
For k, v in cleanup
This.ReturnToExcess(v)
This.StripOut()
}
StripOut(){
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ <= This.Min)
Continue
For key, obj in bin {
If (groupQ - obj.Q >= This.Min){
This.ReturnToExcess(binNum,key)
; Return True
This.StripOut()
}
}
}
}
ReturnToExcess(binNum,tkey:=""){
For key, obj in This.SortGroups[binNum] {
If (tkey="" || tkey && key = tkey)
This.Excess.Push(obj)
}
If (tkey="")
This.SortGroups.Delete(binNum)
Else
This.SortGroups[binNum].RemoveAt(tkey)
}
GroupsAreFull(){
For k, bin in This.SortGroups {
If (This.GetQ(bin) < This.Min)
Return False
}
Return True
}
CheckForFilledGroups(){
; Check if all groups have filled
If !This.GroupsAreFull(){
This.FillBinsFirstFit()
This.FillBinsFirstFit()
This.FillBinsMulti(4)
This.StripOut()
}
This.BreakDownGroups()
While (This.GetQ(This.Excess) >= This.Min) {
This.ReSort(), This.AddGroup(), This.StripOut(), This.SwapForBetter()
}
This.AddGroup()
}
AddGroup(){
This.SortGroups.Push([])
This.FillBinsFirstFit()
This.FillBinsFirstFit()
This.FillBinsMulti(4)
}
FillBinsFirstFit(startingKey:=1) {
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Continue
Results := This.FirstFit(bin,startingKey)
If Results
This.AddToBin(binNum,Results)
}
}
FillBinsFirstFill() {
This.Excess := A.sortBy(This.Excess,"Q")
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Continue
Results := This.FirstFill(bin)
If Results
This.AddToBin(binNum,Results)
}
}
FirstFit(bin,startingKey:=1){
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Return False
For key, obj in This.Excess {
If (key < startingKey)
Continue
If ((groupQ + obj.Q) <= This.Max) {
Return [key]
}
}
}
FirstFill(bin){
groupQ := This.GetQ(bin)
tally := 0
keys := []
If (groupQ >= This.Min)
Return False
For key, obj in This.Excess {
If (groupQ + tally + obj.Q <= This.Max) {
keys.Push(key), tally += obj.Q
}
}
; If groupQ + tally >= This.Min
Return keys
; Return False
}
FillBinsMulti(depth:=2) {
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Continue
Results := This.MultiFit(bin,depth)
If Results
This.AddToBin(binNum,Results)
}
}
MultiFit(bin,depth:=2){
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Return False
For FirstKey, FirstObj in This.Excess {
If ((groupQ + FirstObj.Q) >= This.Min && (groupQ + FirstObj.Q) <= This.Max) {
Return [FirstKey]
} Else If (depth >= 2) {
For SecondKey, SecondObj in This.Excess {
If (FirstKey = SecondKey)
Continue 1
If ((groupQ + FirstObj.Q + SecondObj.Q) >= This.Min && (groupQ + FirstObj.Q + SecondObj.Q) <= This.Max) {
Return [FirstKey,SecondKey]
} Else If (depth >= 3) {
For ThirdKey, ThirdObj in This.Excess {
If (FirstKey = ThirdKey || SecondKey = ThirdKey)
Continue 1
If ((groupQ + FirstObj.Q + SecondObj.Q + ThirdObj.Q) >= This.Min && (groupQ + FirstObj.Q + SecondObj.Q + ThirdObj.Q) <= This.Max) {
Return [FirstKey,SecondKey,ThirdKey]
} Else If (depth >= 4) {
For FourthKey, FourthObj in This.Excess {
If (FirstKey = FourthKey || SecondKey = FourthKey || ThirdKey = FourthKey)
Continue 1
If ((groupQ + FirstObj.Q + SecondObj.Q + ThirdObj.Q + FourthObj.Q) >= This.Min && (groupQ + FirstObj.Q + SecondObj.Q + ThirdObj.Q + FourthObj.Q) <= This.Max) {
Return [FirstKey,SecondKey,ThirdKey,FourthKey]
}
}
}
}
}
}
}
}
}
GetQ(LST){
Return A.sumBy(LST,"Q")
}
GetGroupNum(){
val := 0
While (val < This.Min) {
val += This.Mean
}
This.GroupNum := (This.TotalQ // val)
}
BuildSortGroups(){
This.SortGroups := []
Loop, % This.GroupNum {
This.SortGroups.Push([])
}
}
ReSort(){
For binNum, bin in This.SortGroups {
This.SortGroups[binNum] := A.reverse(A.sortBy(bin,"Q"))
}
This.Excess := A.reverse(A.sortBy(This.Excess,"Q"))
}
AddToBin(binNum,Results){
For k, key in Results {
This.SortGroups[binNum].Push( This.Excess[key] )
}
For k, key in Results {
This.Excess.Delete(key)
}
}
GetCounts(){
objCount := 0
For k, bin in This.SortGroups {
objCount += bin.Count()
}
objCount += This.Excess.Count()
If (objCount != This.TotalNum)
MsgBox % "There is a mismatching number of end objects"
. "`nStarting Count:" This.TotalNum "`tEnd:" objCount
Return objCount
}
}
; Adjust the outcome quality range, and maximum allowed overage
Settings:={}
Settings.minRange := 1
Settings.maxRange := 20
Settings.maxOver := 14
Settings.simulateGems := True
listObj := [], xA := [1,2,3,4,5,6,7,8,9,10,11,12], yA := [1,2,3,4,5]
for _, X in xA {
for _, Y in yA {
If (!Mod(_, 2) || Settings.simulateGems)
listObj.Push({X:X,Y:Y,Q:Random(Settings.minRange,Settings.maxRange)})
}
}
sortedgroup := New SortByNum(listObj,Settings.maxOver)
Class SortByNum {
__New(sortlist,maxOver:=14,min:=40){
; Initiate values, get the total number of potential groups
This.Excess := A.reverse(A.sortBy(sortlist,"Q"))
This.Min := min
This.Max := This.Min + maxOver
This.MaxOver := maxOver
This.TotalQ := This.GetQ(This.Excess)
This.TotalNum := This.Excess.Count()
This.Mean := Floor(A.meanBy(This.Excess,"Q"))
; Find the optimum starting number of groups, then create them
This.GetGroupNum()
This.BuildSortGroups()
; Unload some processing by First Fit
This.FillBinsFirstFit()
This.FillBinsFirstFit()
; Try to intelligently fill the remainder
This.FillBinsMulti(2) ; 2 layers deep to avoid strain on larger list
; Then try to reduce the overQ if any possible swap is available
; This.SwapForBetter()
This.BreakDownGroups()
This.SwapForBetter()
; Now we check for any remaining possible groups
This.CheckForFilledGroups()
This.BreakDownGroups()
This.SwapForBetter()
This.CheckForFilledGroups()
; With all groups hopefully filled, we destroy any below min
This.BreakDownGroups()
This.ReSort()
This.EndCounts := This.GetCounts()
This.ExcessQ := This.GetQ(This.Excess)
This.FinalMessage()
Return This.SortGroups
}
FinalMessage(){
txt := ""
For k, bin in This.SortGroups {
txt .= "<" This.GetQ(bin) ">"
for kk, vv in bin
txt .= " " vv.Q
txt .= "`n"
}
txt .= "Excess:" This.ExcessQ " Count:" This.Excess.Count() "`n"
For k, v in This.Excess {
txt .= v.Q " "
}
MsgBox % txt
}
SwapForBetter(){
While (Results := This.MultiSwap() ) {
binNum := Results.1.1
binKey := Results.1.2
binKey2 := Results.1.3
key := Results.2.1
fetch := This.SortGroups[binNum][binKey]
fetch2 := This.SortGroups[binNum][binKey2]
replace := This.Excess[key]
This.SortGroups[binNum].RemoveAt(binKey2)
This.SortGroups[binNum].RemoveAt(binKey)
This.SortGroups[binNum].Push(replace)
This.Excess.RemoveAt(key)
This.Excess.Push(fetch)
This.Excess.Push(fetch2)
; This.ReSort()
}
While (Results := This.Swap() ) {
binNum := Results.1.1
binKey := Results.1.2
key1 := Results.2.1
key2 := Results.2.2
fetch := This.SortGroups[binNum][binKey]
replace := This.Excess[key1]
If key2 {
replace2 := This.Excess[key2]
This.SortGroups[binNum].Push(replace2)
}
This.SortGroups[binNum].RemoveAt(binKey)
This.SortGroups[binNum].Push(replace)
If key2
This.Excess.RemoveAt(key2)
This.Excess.RemoveAt(key1)
This.Excess.Push(fetch)
; This.ReSort()
}
}
Swap(){
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ <= This.Min)
Continue
overQ := groupQ - This.Min
For binKey, binObj in bin {
; Going through each bin, finding replacements to lower overQ
For key1, obj1 in This.Excess {
newQ := groupQ - binObj.Q + obj1.Q
If (newQ >= This.Min && newQ - This.Min < overQ)
Return [[binNum,binKey],[key1]]
Else {
For key2, obj2 in This.Excess {
If (key1 = key2)
Continue 1
newQ := groupQ - binObj.Q + obj1.Q + obj2.Q
If (newQ >= This.Min && newQ - This.Min < overQ)
Return [[binNum,binKey],[key1,key2]]
}
}
}
}
}
Return False
}
MultiSwap(){
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ <= This.Min)
Continue
overQ := groupQ - This.Min
For binKey, binObj in bin {
; Going through each bin, finding replacements to lower overQ
For binKey2, binObj2 in bin {
If (binKey2 = binKey)
Continue
For key, obj in This.Excess {
newQ := groupQ - binObj.Q - binObj2.Q + obj.Q
If (newQ >= This.Min && newQ - This.Min < overQ){
Return [[binNum,binKey,binKey2],[key]]
}
}
}
}
}
Return False
}
BreakDownGroups(){
cleanup := []
For binNum, bin in This.SortGroups {
If (This.GetQ(bin) < This.Min)
cleanup.Push(binNum)
}
For k, v in cleanup
This.ReturnToExcess(v)
This.StripOut()
}
StripOut(){
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ <= This.Min)
Continue
For key, obj in bin {
If (groupQ - obj.Q >= This.Min){
This.ReturnToExcess(binNum,key)
; Return True
This.StripOut()
}
}
}
}
ReturnToExcess(binNum,tkey:=""){
For key, obj in This.SortGroups[binNum] {
If (tkey="" || tkey && key = tkey)
This.Excess.Push(obj)
}
If (tkey="")
This.SortGroups.Delete(binNum)
Else
This.SortGroups[binNum].RemoveAt(tkey)
}
GroupsAreFull(){
For k, bin in This.SortGroups {
If (This.GetQ(bin) < This.Min)
Return False
}
Return True
}
CheckForFilledGroups(){
; Check if all groups have filled
If !This.GroupsAreFull(){
This.FillBinsFirstFit()
This.FillBinsFirstFit()
This.FillBinsMulti(4)
This.StripOut()
}
This.BreakDownGroups()
While (This.GetQ(This.Excess) >= This.Min) {
This.ReSort(), This.AddGroup(), This.StripOut(), This.SwapForBetter()
}
This.AddGroup()
}
AddGroup(){
This.SortGroups.Push([])
This.FillBinsFirstFit()
This.FillBinsFirstFit()
This.FillBinsMulti(4)
}
FillBinsFirstFit(startingKey:=1) {
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Continue
Results := This.FirstFit(bin,startingKey)
If Results
This.AddToBin(binNum,Results)
}
}
FillBinsFirstFill() {
This.Excess := A.sortBy(This.Excess,"Q")
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Continue
Results := This.FirstFill(bin)
If Results
This.AddToBin(binNum,Results)
}
}
FirstFit(bin,startingKey:=1){
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Return False
For key, obj in This.Excess {
If (key < startingKey)
Continue
If ((groupQ + obj.Q) <= This.Max) {
Return [key]
}
}
}
FirstFill(bin){
groupQ := This.GetQ(bin)
tally := 0
keys := []
If (groupQ >= This.Min)
Return False
For key, obj in This.Excess {
If (groupQ + tally + obj.Q <= This.Max) {
keys.Push(key), tally += obj.Q
}
}
; If groupQ + tally >= This.Min
Return keys
; Return False
}
FillBinsMulti(depth:=2) {
For binNum, bin in This.SortGroups {
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Continue
Results := This.MultiFit(bin,depth)
If Results
This.AddToBin(binNum,Results)
}
}
MultiFit(bin,depth:=2){
groupQ := This.GetQ(bin)
If (groupQ >= This.Min)
Return False
For FirstKey, FirstObj in This.Excess {
If ((groupQ + FirstObj.Q) >= This.Min && (groupQ + FirstObj.Q) <= This.Max) {
Return [FirstKey]
} Else If (depth >= 2) {
For SecondKey, SecondObj in This.Excess {
If (FirstKey = SecondKey)
Continue 1
If ((groupQ + FirstObj.Q + SecondObj.Q) >= This.Min && (groupQ + FirstObj.Q + SecondObj.Q) <= This.Max) {
Return [FirstKey,SecondKey]
} Else If (depth >= 3) {
For ThirdKey, ThirdObj in This.Excess {
If (FirstKey = ThirdKey || SecondKey = ThirdKey)
Continue 1
If ((groupQ + FirstObj.Q + SecondObj.Q + ThirdObj.Q) >= This.Min && (groupQ + FirstObj.Q + SecondObj.Q + ThirdObj.Q) <= This.Max) {
Return [FirstKey,SecondKey,ThirdKey]
} Else If (depth >= 4) {
For FourthKey, FourthObj in This.Excess {
If (FirstKey = FourthKey || SecondKey = FourthKey || ThirdKey = FourthKey)
Continue 1
If ((groupQ + FirstObj.Q + SecondObj.Q + ThirdObj.Q + FourthObj.Q) >= This.Min && (groupQ + FirstObj.Q + SecondObj.Q + ThirdObj.Q + FourthObj.Q) <= This.Max) {
Return [FirstKey,SecondKey,ThirdKey,FourthKey]
}
}
}
}
}
}
}
}
}
GetQ(LST){
Return A.sumBy(LST,"Q")
}
GetGroupNum(){
val := 0
While (val < This.Min) {
val += This.Mean
}
This.GroupNum := (This.TotalQ // val)
}
BuildSortGroups(){
This.SortGroups := []
Loop, % This.GroupNum {
This.SortGroups.Push([])
}
}
ReSort(){
For binNum, bin in This.SortGroups {
This.SortGroups[binNum] := A.reverse(A.sortBy(bin,"Q"))
}
This.Excess := A.reverse(A.sortBy(This.Excess,"Q"))
}
AddToBin(binNum,Results){
For k, key in Results {
This.SortGroups[binNum].Push( This.Excess[key] )
}
For k, key in Results {
This.Excess.Delete(key)
}
}
GetCounts(){
objCount := 0
For k, bin in This.SortGroups {
objCount += bin.Count()
}
objCount += This.Excess.Count()
If (objCount != This.TotalNum)
MsgBox % "There is a mismatching number of end objects"
. "`nStarting Count:" This.TotalNum "`tEnd:" objCount
Return objCount
}
}
Random(min:=1,max:=100){
Random, retval ,% Min,% Max
Return retval
}
; Make a MsgBox Printout of an array
MsgBoxVals(obj,indent:=0){
txt := ""
Loop % indent
spacing .= " "
If IsObject(obj)
{
txt .= spacing
For k, v in obj
{
txt .= k "="
. (IsObject(v)?"{`n":v (A_Index != obj.Count()?", ":""))
If IsObject(v)
txt .= MsgBoxVals(v,indent+1) " }`n"
}
} Else {
txt := obj
}
If indent
Return txt
Else
MsgBox % txt
}
spacing(num,str:=" "){
ret := ""
Loop % num {
ret .= str
}
return ret
}
class biga {
; --- Static Variables ---
static throwExceptions := true
static limit := -1
static _guardedMethods := ["trim"]
; --- Static Methods ---
chunk(param_array,param_size:=1) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
l_array := []
param_array := this.clone(param_array)
; create
; keep working till the parameter array is empty
while (param_array.count() > 0) {
l_innerArr := []
; fill the inner array to the max size of the size parameter
loop, % param_size {
; exit loop if there is nothing left in parameter array to work with
if (param_array.count() == 0) {
break
}
l_innerArr.push(param_array.removeAt(1))
}
l_array.push(l_innerArr)
}
return l_array
}
compact(param_array) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
l_array := []
; create
for key, value in param_array {
if (value == "" || value == 0) {
continue
}
l_array.push(value)
}
return l_array
}
concat(param_array,param_values*) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
l_array := this.clone(param_array)
; create
for index, object in param_values {
; push on any plain values
if (!isObject(object)) {
l_array.push(object)
} else { ;push object values 1 level deep
for index2, object2 in object {
l_array.push(object2)
}
}
}
return l_array
}
depthOf(param_array,param_depth:=1) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
for key, value in param_array {
if (isObject(value)) {
param_depth++
param_depth := this.depthOf(value, param_depth)
}
}
return param_depth
}
difference(param_array,param_values*) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
l_array := this.clone(param_array)
; create
; loop all Variadic inputs
for i, obj in param_values {
for key, value in obj {
loop {
foundIndex := this.indexOf(l_array, value)
if (foundIndex != -1) {
l_array.removeAt(foundIndex)
}
} until (foundIndex == -1)
}
}
return l_array
}
drop(param_array,param_n:=1) {
if (!this.isNumber(param_n)) {
this._internal_ThrowException()
}
; prepare
if (isObject(param_array)) {
l_array := this.clone(param_array)
}
if (this.isStringLike(param_array)) {
l_array := strSplit(param_array)
}
; create
loop, % param_n {
l_array.RemoveAt(1)
}
; return empty array if empty
if (l_array.count() == 0) {
return []
}
return l_array
}
dropRight(param_array,param_n:=1) {
if (!this.isNumber(param_n)) {
this._internal_ThrowException()
}
; prepare
if (isObject(param_array)) {
l_array := this.clone(param_array)
}
if (this.isStringLike(param_array)) {
l_array := strSplit(param_array)
}
; create
loop, % param_n {
l_array.removeAt(l_array.count())
}
; return empty array if empty
if (l_array.count() == 0) {
return []
}
return l_array
}
dropRightWhile(param_array,param_predicate:="__identity") {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; validate
; return empty array if empty
if (param_array.count() == 0) {
return []
}
l_array := this.reverse(this.cloneDeep(param_array))
return this.reverse(this.dropWhile(l_array, param_predicate))
}
dropWhile(param_array,param_predicate:="__identity") {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; validate
; return empty array if empty
if (param_array.count() == 0) {
return []
}
; prepare
shorthand := this._internal_differenciateShorthand(param_predicate, param_array)
if (shorthand != false) {
param_predicate := this._internal_createShorthandfn(param_predicate, param_array)
}
; create
l_array := this.cloneDeep(param_array)
l_droppableElements := 0
for key, value in l_array {
if (this.isCallable(param_predicate)) {
if (param_predicate.call(value, key, l_array)) {
l_droppableElements++
} else {
break
}
}
}
if (l_droppableElements >= 1) {
l_array.removeAt(1, l_droppableElements)
}
return l_array
}
fill(param_array,param_value:="",param_start:=1,param_end:=-1) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
l_array := this.clone(param_array)
if (param_end == -1) {
param_end := this.size(param_array)
}
; create
for key, value in l_array {
if (key >= param_start && key <= param_end) {
l_array[key] := param_value
}
}
return l_array
}
findIndex(param_array,param_predicate,param_fromindex:=1) {
if (!isObject(param_array) || !this.isNumber(param_fromindex)) {
this._internal_ThrowException()
}
; prepare
l_array := []
shorthand := this._internal_differenciateShorthand(param_predicate, param_array)
if (shorthand != false) {
param_predicate := this._internal_createShorthandfn(param_predicate, param_array)
}
; create
for key, value in param_array {
if (param_fromIndex > A_Index) {
continue
}
if (this.isCallable(param_predicate)) {
if (param_predicate.call(value, key, param_array)) {
return key
}
}
}
return -1
}
findLastIndex(param_array,param_value,param_fromIndex:=1) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; create
l_array := this.reverse(this.cloneDeep(param_array))
l_count := this.size(l_array)
l_foundIndex := this.findIndex(l_array, param_value, param_fromIndex)
if (l_foundIndex < 0) {
return -1
} else {
finalIndex := l_count + 1
finalIndex := finalIndex - l_foundIndex
}
return finalIndex
}
flatten(param_array) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
l_obj := []
; create
for Index, Object in param_array {
if (isObject(Object)) {
for Index2, Object2 in Object {
l_obj.push(Object2)
}
} else {
l_obj.push(Object)
}
}
return l_obj
}
flattenDeep(param_array) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
l_depth := this.depthOf(param_array)
; create
return this.flattenDepth(param_array, l_depth)
}
flattenDepth(param_array,param_depth:=1) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
l_obj := this.cloneDeep(param_array)
; create
loop, % param_depth {
l_obj := this.flatten(l_obj)
}
return l_obj
}
fromPairs(param_pairs) {
if (!isObject(param_pairs)) {
this._internal_ThrowException()
}
; prepare
l_obj := {}
; create
for key, value in param_pairs {
l_obj[value[1]] := value[2]
}
return l_obj
}
head(param_array) {
; create
return this.take(param_array)[1]
}
indexOf(param_array,param_value,fromIndex:=1) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
if (isObject(param_value)) {
param_value := this._internal_MD5(param_value)
param_array := this.map(param_array, this._internal_MD5)
}
; create
for index, value in param_array {
if (A_Index < fromIndex) {
continue
}
if (value != param_value) {
continue
} else {
return index
}
}
return -1
}
initial(param_array) {
; prepare
if (isObject(param_array)) {
l_array := this.clone(param_array)
}
if (this.isStringLike(param_array)) {
l_array := StrSplit(param_array)
}
; create
; return empty array if empty
if (l_array.count() == 0) {
return []
}
return % this.dropRight(l_array)
}
intersection(param_arrays*) {
for key, value in param_arrays {
if (!isObject(value)) {
this._internal_ThrowException()
}
}
; prepare
tempArray := A.cloneDeep(param_arrays[1])
param_arrays.removeAt(1) ;no need to check 1st array against itself, this does not mutate the input args
l_array := []
; create
for key, value in tempArray { ;for each value in first array
for key2, value2 in param_arrays { ;for each array sent to the method
; search all arrays for value in first array
if (this.indexOf(value2, value) != -1) {
found := true
} else {
found := false
break
}
}
if (found && this.indexOf(l_array, value) == -1) {
l_array.push(value)
}
}
return l_array
}
join(param_array,param_sepatator:=",") {
if (!isObject(param_array) || isObject(param_sepatator)) {
this._internal_ThrowException()
}
; prepare
l_array := this.clone(param_array)
; create
for l_key, l_value in l_array {
if (A_Index == 1) {
l_string := "" l_value
continue
}
l_string := l_string param_sepatator l_value
}
return l_string
}
last(param_array) {
; prepare
if (isObject(param_array)) {
param_array := this.clone(param_array)
}
if (this.isStringLike(param_array)) {
param_array := strSplit(param_array)
}
; create
return param_array.pop()
}
lastIndexOf(param_array,param_value,param_fromIndex:=0) {
if (param_fromIndex == 0) {
param_fromIndex := param_array.count()
}
; create
for Index, value in param_array {
Index -= 1
vNegativeIndex := param_array.count() - Index
if (vNegativeIndex > param_fromIndex) { ;skip search
continue
}
if (this.isEqual(param_array[vNegativeIndex], param_value)) {
return vNegativeIndex
}
}
return -1
}
nth(param_array,param_n:=1) {
if (!this.isNumber(param_n)) {
this._internal_ThrowException()
}
; prepare
if (isObject(param_array)) {
l_array := this.clone(param_array)
}
if (this.isStringLike(param_array)) {
l_array := strSplit(param_array)
}
if (param_n == 0) {
param_n := 1
}
; create
if (l_array.count() < param_n) { ;return "" if n is greater than the array's size
return ""
}
if (param_n > 0) {
return l_array[param_n]
}
; return empty array if empty
if (l_array.count() == 0) {
return ""
}
; if called with negative n, call self with reversed array and positive number
l_array := this.reverse(l_array)
param_n := 0 - param_n
return this.nth(l_array, param_n)
}
reverse(param_collection) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
l_collection := this.cloneDeep(param_collection)
l_array := []
; create
while (l_collection.count() != 0) {
l_array.push(l_collection.pop())
}
return l_array
}
slice(param_array,param_start:=1,param_end:=0) {
if (!this.isNumber(param_start)) {
this._internal_ThrowException()
}
if (!this.isNumber(param_end)) {
this._internal_ThrowException()
}
; prepare
if (this.isStringLike(param_array)) {
param_array := strSplit(param_array)
}
if (param_end == 0) {
param_end := param_array.count()
}
l_array := []
; create
for key, value in param_array {
if (A_Index >= param_start && A_Index <= param_end) {
l_array.push(value)
}
}
return l_array
}
sortedIndex(param_array,param_value) {
; prepare
if (param_value < param_array[1]) {
return 1
}
; create
loop, % param_array.count() {
if (param_array[A_Index] < param_value && param_value < param_array[A_Index+1]) {
return A_Index + 1
}
}
return param_array.count() + 1
}
sortedUniq(param_collection) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
l_array := []
; create
for key, value in param_collection {
printedelement := this._printObj(param_collection[key])
if (l_temp != printedelement) {
l_temp := printedelement
l_array.push(value)
}
}
return l_array
}
tail(param_array) {
; create
return this.drop(param_array)
}
take(param_array,param_n:=1) {
if (!this.isNumber(param_n)) {
this._internal_ThrowException()
}
; prepare
if (isObject(param_array)) {
param_array := this.clone(param_array)
}
if (this.isStringLike(param_array)) {
param_array := strSplit(param_array)
}
l_array := []
; create
for key, value in param_array {
if (param_n < A_Index) {
break
}
l_array.push(value)
}
; return empty array if empty
if (l_array.count() == 0 || param_n == 0) {
return []
}
return l_array
}
takeRight(param_array,param_n:=1) {
if (!this.isNumber(param_n)) {
this._internal_ThrowException()
}
; prepare
if (isObject(param_array)) {
param_array := this.clone(param_array)
}
if (this.isStringLike(param_array)) {
param_array := strSplit(param_array)
}
l_array := []
; create
loop, % param_n {
if (param_array.count() == 0) {
continue
}
vvalue := param_array.pop()
l_array.push(vvalue)
}
; return empty array if empty
if (l_array.count() == 0 || param_n == 0) {
return []
}
return this.reverse(l_array)
}
union(param_arrays*) {
; prepare
l_array := []
; create
for key, Array in param_arrays {
if (isObject(Array)) {
l_array := this.concat(l_array, Array)
} else {
l_array.push(Array)
}
}
return this.uniq(l_array)
}
uniq(param_collection) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
tempArray := []
l_array := []
; create
for key, value in param_collection {
l_printedElement := this._internal_MD5(param_collection[key])
if (this.indexOf(tempArray, l_printedElement) == -1) {
tempArray.push(l_printedElement)
l_array.push(value)
}
}
return l_array
}
without(param_array,param_values*) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
l_array := this.clone(param_array)
; create
for i, val in param_values {
while (foundindex := this.indexOf(l_array, val) != -1) {
l_array.removeAt(foundindex)
}
}
return l_array
}
zip(param_arrays*) {
if (!isObject(param_arrays)) {
this._internal_ThrowException()
}
l_array := []
; loop all Variadic inputs
for key, value in param_arrays {
; for each value in the supplied set of array(s)
for key2, value2 in value {
loop, % value.count() {
if (key2 == A_Index) {
; create array if not encountered yet
if (isObject(l_array[A_Index]) == false) {
l_array[A_Index] := []
}
; push values onto the array for their position in the supplied arrays
l_array[A_Index].push(value2)
}
}
}
}
return l_array
}
zipObject(param_props,param_values) {
if (!isObject(param_props)) {
param_props := []
}
if (!isObject(param_values)) {
param_values := []
}
l_obj := {}
for key, value in param_props {
l_obj[value] := param_values[A_Index]
}
return l_obj
}
count(param_collection,param_predicate,param_fromIndex:=1) {
; prepare
shorthand := this._internal_differenciateShorthand(param_predicate, param_collection)
if (shorthand != false) {
param_predicate := this._internal_createShorthandfn(param_predicate, param_collection)
}
; create
l_count := 0
if (this.isAlnum(param_collection) || this.isString(param_collection)) {
; cut fromindex length off from start of string if specified fromIndex > 1
if (param_fromIndex > 1) {
param_collection := subStr(param_collection, param_fromIndex, strLen(param_collection))
}
; count by replacing all occurances
strReplace(param_collection, param_predicate, "", l_count)
return l_count
}
for key, value in param_collection {
if (param_fromIndex > A_Index) {
continue
}
if (this.isCallable(param_predicate)) {
if (param_predicate.call(value, key, param_collection) == true) {
l_count++
continue
}
}
if (this.isEqual(value, param_predicate)) {
l_count++
}
}
return l_count
}
every(param_collection,param_predicate) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_predicate, param_collection)
if (shorthand != false) {
param_predicate := this._internal_createShorthandfn(param_predicate, param_collection)
}
; create
for key, value in param_collection {
if (this.isCallable(param_predicate)) {
if (param_predicate.call(value, key, param_collection) == true) {
continue
}
return false
}
}
return true
}
filter(param_collection,param_predicate:="__identity") {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_predicate, param_collection)
if (shorthand != false) {
param_predicate := this._internal_createShorthandfn(param_predicate, param_collection)
}
l_paramAmmount := param_predicate.maxParams
if (l_paramAmmount == 3) {
collectionClone := this.cloneDeep(param_collection)
}
l_array := []
; create
for key, value in param_collection {
; functor
if (this.isCallable(param_predicate)) {
if (l_paramAmmount == 3) {
if (param_predicate.call(value, key, collectionClone)) {
l_array.push(value)
continue
}
}
if (param_predicate.call(value, key)) {
l_array.push(value)
}
}
}
return l_array
}
find(param_collection,param_predicate,param_fromindex:=1) {
if (!isObject(param_collection) || !this.isNumber(param_fromindex)) {
this._internal_ThrowException()
}
; create
foundIndex := this.findIndex(param_collection, param_predicate, param_fromindex)
if (foundIndex != -1) {
return param_collection[foundIndex]
}
return false
}
findLast(param_collection,param_predicate) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; create
return this.find(this.reverse(param_collection), param_predicate)
}
forEach(param_collection,param_iteratee:="__identity") {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
if (!isFunc(param_iteratee)) {
boundFunc := param_iteratee.bind(this)
}
if (l_paramAmmount == 3) {
collectionClone := this.cloneDeep(param_collection)
}
; create
; run against every value in the collection
for key, value in param_collection {
if (!boundFunc) { ; is property/string
;nothing currently
}
if (!boundFunc.call(value, key, collectionClone)) {
vIteratee := param_iteratee.call(value, key, collectionClone)
}
; exit iteration early by explicitly returning false
if (vIteratee == false) {
return param_collection
}
}
return param_collection
}
groupBy(param_collection,param_iteratee:="__identity") {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_iteratee, param_collection)
if (shorthand != false) {
param_iteratee := this._internal_createShorthandfn(param_iteratee, param_collection)
}
; create
l_array := []
for key, value in param_collection {
vIteratee := 0
; functor
if (this.isCallable(param_iteratee) || !vIteratee) {
vIteratee := param_iteratee.call(value)
}
; create array at key if not encountered yet
if (!l_array.haskey(vIteratee)) {
l_array[vIteratee] := []
}
; add value to this key
l_array[vIteratee].push(value)
}
return l_array
}
includes(param_collection,param_value,param_fromIndex:=1) {
if (!this.isNumber(param_fromIndex)) {
this._internal_ThrowException()
}
; prepare
if (isObject(param_value)) {
param_value := this._internal_MD5(param_value)
param_collection := this.map(param_collection, this._internal_MD5)
}
; create
if (isObject(param_collection)) {
for key, value in param_collection {
if (param_fromIndex > A_Index) {
continue
}
if (this.isEqual(value, param_value)) {
return true
}
}
return false
} else {
; RegEx
if (RegEx_value := this._internal_JSRegEx(param_value)) {
return RegExMatch(param_collection, RegEx_value, RE, param_fromIndex)
}
; Normal string search
if (A_StringCaseSense == "On") {
StringCaseSense := 1
} else {
StringCaseSense := 0
}
if (InStr(param_collection, param_value, StringCaseSense, param_fromIndex)) {
return true
} else {
return false
}
}
}
keyBy(param_collection,param_iteratee:="__identity") {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_iteratee, param_collection)
if (shorthand == ".property") {
param_iteratee := this._internal_createShorthandfn(param_iteratee, param_collection)
}
l_obj := {}
; run against every value in the collection
for key, value in param_collection {
if (this.isCallable(param_iteratee)) {
vIteratee := param_iteratee.call(value)
}
if (l_paramAmmount == 3) {
if (!boundFunc.call(value, key, collectionClone)) {
vIteratee := param_iteratee.call(value, key, collectionClone)
}
}
objRawSet(l_obj, vIteratee, value)
}
return l_obj
}
map(param_collection,param_iteratee:="__identity") {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_iteratee, param_collection)
if (shorthand == ".property") {
param_iteratee := this.property(param_iteratee)
}
if (this.startsWith(param_iteratee.name, this.base.__Class ".")) { ;if starts with "biga."
guarded := this.includes(this._guardedMethods, strSplit(param_iteratee.name, ".").2)
param_iteratee := param_iteratee.bind(this)
}
l_collection := this.cloneDeep(param_collection)
l_array := []
; create
for key, value in param_collection {
if (param_iteratee == "__identity") {
l_array.push(value)
continue
}
; functor
if (guarded) {
l_array.push(param_iteratee.call(value))
continue
}
if (this.isCallable(param_iteratee)) {
l_array.push(param_iteratee.call(value, key, l_collection))
}
}
return l_array
}
partition(param_collection,param_predicate) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
trueArray := []
falseArray := []
shorthand := this._internal_differenciateShorthand(param_predicate, param_collection)
if (shorthand != false) {
param_predicate := this._internal_createShorthandfn(param_predicate, param_collection)
}
; create
for key, value in param_collection {
if (param_predicate.call(value) == true) {
trueArray.push(value)
} else {
falseArray.push(value)
}
}
return [trueArray, falseArray]
}
reject(param_collection,param_predicate) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_predicate, param_collection)
if (shorthand != false) {
param_predicate := this._internal_createShorthandfn(param_predicate, param_collection)
}
l_array := []
; create
for key, value in param_collection {
; functor
; predefined !functor handling (slower as it .calls blindly)
if (this.isCallable(param_predicate)) {
if (!param_predicate.call(value)) {
l_array.push(value)
}
continue
}
}
return l_array
}
sample(param_collection) {
if (!this.isStringLike(param_collection) && !isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
if (this.isStringLike(param_collection)) {
param_collection := strSplit(param_collection)
}
if (param_collection.count() != param_collection.length()) {
l_array := this.map(param_collection)
} else {
l_array := param_collection.clone()
}
; create
randomIndex := this.random(1, l_array.count())
return l_array[randomIndex]
}
sampleSize(param_collection,param_sampleSize:=1) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; return immediately if array is smaller than requested sampleSize
if (param_sampleSize > param_collection.count()) {
return param_collection
}
; prepare
if (this.isStringLike(param_collection)) {
param_collection := strSplit(param_collection)
}
l_order := A.shuffle(this.keys(param_collection))
l_array := []
; create
loop, % param_sampleSize
{
ordervalue := l_order.pop()
l_array.push(param_collection[ordervalue])
}
return l_array
}
shuffle(param_collection) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
l_array := this.clone(param_collection)
; create
l_index := l_array.count()
loop, % l_index - 1 {
random, randomIndex, 1, % l_index
l_tempVar := l_array[l_index]
l_array[l_index] := l_array[randomIndex]
l_array[randomIndex] := l_tempVar
l_index--
}
return l_array
}
size(param_collection) {
; prepare
if (param_collection.count() == 0) {
return ""
}
; create
if (max := this.max([param_collection.count(), param_collection.maxIndex()])) {
return max
}
return strLen(param_collection)
}
some(param_collection,param_predicate) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_predicate, param_collection)
if (shorthand != false) {
param_predicate := this._internal_createShorthandfn(param_predicate, param_collection)
}
; create
for key, value in param_collection {
if (this.isCallable(param_predicate)) {
if (param_predicate.call(value, key, param_collection) = true) {
return true
}
}
}
return false
}
sortBy(param_collection,param_iteratees:="__identity") {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
if (this.startsWith(param_iteratees.name, this.base.__Class ".")) { ;if starts with "biga."
param_iteratees := param_iteratees.bind(this)
}
l_array := []
; create
; no param_iteratees
if (param_iteratees == "__identity") {
return this._internal_sort(param_collection)
}
; property
if (this.isAlnum(param_iteratees)) {
return this._internal_sort(param_collection, param_iteratees)
}
; own method or function
if (this.isCallable(param_iteratees)) {
for key, value in param_collection {
l_array[A_Index] := {}
l_array[A_Index].value := value
l_array[A_Index].key := param_iteratees.call(value)
}
l_array := this._internal_sort(l_array, "key")
return this.map(l_array, "value")
}
; shorthand/multiple keys
if (isObject(param_iteratees)) {
l_array := this.cloneDeep(param_collection)
; sort the collection however many times is requested by the shorthand identity
for key, value in param_iteratees {
l_array := this._internal_sort(l_array, value)
}
return l_array
}
return -1
}
_internal_sort(param_collection,param_iteratees:="") {
l_array := this.cloneDeep(param_collection)
; associative arrays
if (param_iteratees != "") {
for Index, obj in l_array {
out .= obj[param_iteratees] "+" Index "|" ; "+" allows for sort to work with just the value
; out will look like: value+index|value+index|
}
lastvalue := l_array[Index, param_iteratees]
} else {
; regular arrays
for Index, obj in l_array {
out .= obj "+" Index "|"
}
lastvalue := l_array[l_array.count()]
}
if (this.isNumber(lastvalue)) {
sortType := "N"
}
stringTrimRight, out, out, 1 ; remove trailing |
sort, out, % "D| " sortType
arrStorage := []
loop, parse, out, |
{
arrStorage.push(l_array[SubStr(A_LoopField, InStr(A_LoopField, "+") + 1)])
}
return arrStorage
}
; /--\--/--\--/--\--/--\--/--\
; Internal functions
; \--/--\--/--\--/--\--/--\--/
_printObj(param_obj) {
if (!isObject(param_obj)) {
return """" param_obj """"
}
if this._internal_IsCircle(param_obj) {
this._internal_ThrowException()
}
for key, value in param_obj {
if key is not Number
{
Output .= """" . key . """:"
} else {
Output .= key . ":"
}
if (isObject(value)) {
Output .= "[" . this._printObj(value) . "]"
} else if value is not number
{
Output .= """" . value . """"
} else {
Output .= value
}
Output .= ", "
}
StringTrimRight, OutPut, OutPut, 2
return OutPut
}
print(param_obj) {
if (!isObject(param_obj)) {
return """" param_obj """"
}
if this._internal_IsCircle(param_obj) {
this._internal_ThrowException()
}
return this._printObj(param_obj)
}
_internal_MD5(param_string, case := 0) {
if (isObject(param_string)) {
param_string := this.print(param_string)
}
static MD5_DIGEST_LENGTH := 16
hModule := DllCall("LoadLibrary", "Str", "advapi32.dll", "Ptr")
, VarSetCapacity(MD5_CTX, 104, 0), DllCall("advapi32\MD5Init", "Ptr", &MD5_CTX)
, DllCall("advapi32\MD5Update", "Ptr", &MD5_CTX, "AStr", param_string, "UInt", StrLen(param_string))
, DllCall("advapi32\MD5Final", "Ptr", &MD5_CTX)
loop % MD5_DIGEST_LENGTH {
o .= Format("{:02" (case ? "X" : "x") "}", NumGet(MD5_CTX, 87 + A_Index, "UChar"))
}
DllCall("FreeLibrary", "Ptr", hModule)
return o
}
_internal_JSRegEx(param_string) {
if (!this.isString(param_string) && !this.isAlnum(param_string)) {
this._internal_ThrowException()
}
if (this.startsWith(param_string, "/") && this.startsWith(param_string, "/", StrLen(param_string))) {
return SubStr(param_string, 2, StrLen(param_string) - 2)
}
return false
}
_internal_differenciateShorthand(param_shorthand,param_objects:="") {
if (this.startsWith(param_shorthand.name, this.base.__Class ".")) { ;if starts with "biga."
return "_classMethod"
}
if (isObject(param_shorthand) && !this.isCallable(param_shorthand)) {
if (param_shorthand.maxIndex() != param_shorthand.count()) {
return ".matches"
}
return ".matchesProperty"
}
if (this.isStringLike(param_shorthand) && isObject(param_objects)) {
for key, value in param_objects {
if (value.hasKey(param_shorthand)) {
return ".property"
}
}
}
return false
}
_internal_createShorthandfn(param_shorthand,param_objects) {
shorthand := this._internal_differenciateShorthand(param_shorthand, param_objects)
if (shorthand == "_classMethod") {
return param_shorthand.bind(this)
}
if (shorthand == ".matches") {
return this.matches(param_shorthand)
}
if (shorthand == ".matchesProperty") {
return this.matchesProperty(param_shorthand[1], param_shorthand[2])
}
if (shorthand == ".property") {
return this.property(param_shorthand)
}
}
_internal_ThrowException() {
if (this.throwExceptions == true) {
throw Exception("Type Error", -2)
}
}
_internal_inStr(param_haystack,param_needle,param_fromIndex:=1,param_occurance:=1) {
; used inplace of inStr to follow A_StringCaseSense
if (A_StringCaseSense == "On") {
StringCaseSense := 1
} else {
StringCaseSense := 0
}
if (position := inStr(param_collection, param_value, StringCaseSense, param_fromIndex, param_occurance)) {
return position
} else {
return false
}
}
isFalsey(param) {
if (isObject(param)) {
return false
}
if (param == "" || param == 0) {
return true
}
return false
}
isStringLike(param) {
if (isObject(param)) {
return false
}
if (this.isString(param) || this.isAlnum(param)) {
return true
}
return false
}
clone(param_value) {
if (isObject(param_value)) {
return param_value.Clone()
} else {
return param_value
}
}
cloneDeep(param_array) {
Objs := {}
Obj := param_array.Clone()
Objs[&param_array] := Obj ; Save this new array
for key, value in Obj {
if (isObject(value)) ; if it is a subarray
Obj[key] := Objs[&value] ; if we already know of a refrence to this array
? Objs[&value] ; Then point it to the new array
: this.clone(value, Objs) ; Otherwise, clone this sub-array
}
return Obj
}
isAlnum(param) {
if (isObject(param)) {
return false
}
if param is alnum
{
return true
}
return false
}
isArray(param) {
if (param.GetCapacity()) {
return true
}
return false
}
isBoolean(param) {
if this.isEqual(param, 1) {
return true
}
if this.isEqual(param, 0) {
return true
}
return false
}
isCallable(param) {
fn := numGet(&(_ := Func("InStr").bind()), "Ptr")
return (isFunc(param) || (isObject(param) && (numGet(&param, "Ptr") = fn)))
}
isEqual(param_value,param_other*) {
; prepare
if (isObject(param_value)) {
l_array := []
param_value := this._printObj(param_value)
loop, % param_other.count() {
l_array.push(this._printObj(param_other[A_Index]))
}
} else {
l_array := this.cloneDeep(param_other)
}
; create
loop, % l_array.count() {
if (param_value != l_array[A_Index]) { ; != follows StringCaseSense
return false
}
}
return true
}
isFloat(param) {
if (isObject(param)) {
return false
}
if param is float
{
return true
}
return false
}
isInteger(param) {
if param is integer
{
if (!this.isString(param)) {
return true
}
}
return false
}
isMatch(param_object,param_source) {
for key, value in param_source {
if (param_object[key] == value) {
continue
} else {
return false
}
}
return true
}
isNumber(param) {
if (isObject(param)) {
return false
}
if param is number
{
return true
}
return false
}
isObject(param) {
if (isObject(param)) {
return true
}
return false
}
isString(param) {
if (isObject(param)) {
return false
}
if (ObjGetCapacity([param], 1) == "") {
return false
}
return true
}
isUndefined(param_value) {
if (param_value == "") {
return true
}
return false
}
toString(param_value) {
if (isObject(param_value)) {
return this.join(param_value, ",")
} else {
return "" param_value
}
}
add(param_augend,param_addend) {
if (!this.isNumber(param_augend) || !this.isNumber(param_addend)) {
this._internal_ThrowException()
}
; create
return param_augend + param_addend
}
ceil(param_number,param_precision:=0) {
if (!this.isNumber(param_number) || !this.isNumber(param_precision)) {
this._internal_ThrowException()
}
if (param_precision == 0) { ; regular ceil
return ceil(param_number)
}
l_offset := 0.5 / (10**param_precision)
if (param_number < 0 && param_precision >= 1) {
l_offset /= 10 ; adjust offset for negative numbers and positive param_precision
}
if (param_precision >= 1) {
l_decChar := strlen( substr(param_number, instr(param_number, ".") + 1) ) ; count the number of decimal characters
l_sum := format("{:." this.max([l_decChar, param_precision]) + 1 "f}", param_number + l_offset)
} else {
l_sum := param_number + l_offset
}
l_sum := trim(l_sum, "0") ; trim zeroes
l_value := (SubStr(l_sum, 0) = "5") && param_number != l_sum ? SubStr(l_sum, 1, -1) : l_sum ; if last char is 5 then remove it unless it is part of the original string
return Round(l_value, param_precision)
}
divide(param_dividend,param_divisor) {
if (!this.isNumber(param_dividend) || !this.isNumber(param_divisor)) {
this._internal_ThrowException()
}
; create
return param_dividend / param_divisor
}
floor(param_number,param_precision:=0) {
if (!this.isNumber(param_number) || !this.isNumber(param_precision)) {
this._internal_ThrowException()
}
if (param_precision == 0) { ; regular floor
return floor(param_number)
}
l_offset := -0.5 / (10**param_precision)
if (param_number < 0 && param_precision >= 1) {
l_offset /= 10 ; adjust offset for negative numbers and positive param_precision
}
if (param_precision >= 1) {
l_decChar := strlen( substr(param_number, instr(param_number, ".") + 1) ) ; count the number of decimal characters
l_sum := format("{:." this.max([l_decChar, param_precision]) + 1 "f}", param_number + l_offset)
} else {
l_sum := param_number + l_offset
}
l_sum := trim(l_sum, "0") ; trim zeroes
l_value := (SubStr(l_sum, 0) = "5") && param_number != l_sum ? SubStr(l_sum, 1, -1) : l_sum ; if last char is 5 then remove it unless it is part of the original string
return Round(l_value, param_precision)
}
max(param_array) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
l_max := ""
for key, value in param_array {
if (l_max < value || this.isUndefined(l_max)) {
l_max := value
}
}
return l_max
}
mean(param_array) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
l_sum := 0
for key, value in param_array {
l_sum += value
}
return l_sum / this.size(param_array)
}
meanBy(param_array,param_iteratee:="__identity") {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
if (!isFunc(param_iteratee)) {
boundFunc := param_iteratee.bind(this)
}
shorthand := this._internal_differenciateShorthand(param_iteratee, param_array)
if (shorthand != false) {
param_iteratee := this._internal_createShorthandfn(param_iteratee, param_array)
}
; prepare
if (l_paramAmmount == 3) {
arrayClone := this.cloneDeep(param_array)
}
l_total := 0
; run against every value in the array
for key, value in param_array {
; functor
if (this.isCallable(param_iteratee)) {
l_iteratee := param_iteratee.call(value)
}
l_total += l_iteratee
}
return l_total / param_array.count()
}
min(param_array) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
l_min := ""
for key, value in param_array {
if (l_min > value || this.isUndefined(l_min)) {
l_min := value
}
}
return l_min
}
multiply(param_multiplier,param_multiplicand) {
if (!this.isNumber(param_multiplier) || !this.isNumber(param_multiplicand)) {
this._internal_ThrowException()
}
; create
return param_multiplier * param_multiplicand
}
round(param_number,param_precision:=0) {
if (!this.isNumber(param_number) || !this.isNumber(param_precision)) {
this._internal_ThrowException()
}
; create
return round(param_number, param_precision)
}
subtract(param_minuend,param_subtrahend) {
if (!this.isNumber(param_minuend) || !this.isNumber(param_subtrahend)) {
this._internal_ThrowException()
}
; create
param_minuend -= param_subtrahend
return param_minuend
}
sum(param_array) {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
vSum := 0
for key, value in param_array {
vSum += value
}
return vSum
}
sumBy(param_array,param_iteratee:="__identity") {
if (!isObject(param_array)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_iteratee, param_array)
if (shorthand = ".property") {
param_iteratee := this._internal_createShorthandfn(param_iteratee, param_array)
}
l_total := 0
; run against every value in the array
for key, value in param_array {
; functor
if (this.isCallable(param_iteratee)) {
l_iteratee := param_iteratee.call(value)
}
l_total += l_iteratee
}
return l_total
}
clamp(param_number,param_lower,param_upper) {
if (!this.isNumber(param_number) || !this.isNumber(param_lower) || !this.isNumber(param_upper)) {
this._internal_ThrowException()
}
; check the lower bound
if (param_number < param_lower) {
param_number := param_lower
}
; check the upper bound
if (param_number > param_upper) {
param_number := param_upper
}
return param_number
}
inRange(param_number,param_lower,param_upper) {
if (!this.isNumber(param_number) || !this.isNumber(param_lower) || !this.isNumber(param_upper)) {
this._internal_ThrowException()
}
; prepare
if (param_lower > param_upper) {
l_temp := param_lower
param_lower := param_upper
param_upper := l_temp
}
; check the bounds
if (param_number > param_lower && param_number < param_upper) {
return true
}
return false
}
random(param_lower:=0,param_upper:=1,param_floating:=false) {
if (!this.isNumber(param_lower) || !this.isNumber(param_upper) || !this.isNumber(param_floating)) {
this._internal_ThrowException()
}
; prepare
if (param_lower > param_upper) {
l_temp := param_lower
param_lower := param_upper
param_upper := l_temp
}
if (param_floating) {
param_lower += 0.0
param_upper += 0.0
}
; create
random, vRandom, param_lower, param_upper
return vRandom
}
defaults(param_object,param_sources*) {
if (!isObject(param_object)) {
this._internal_ThrowException()
}
; prepare
l_obj := this.clone(param_object)
param_sources := this.reverse(param_sources)
; create
for Index, Object in param_sources {
for key, value in Object {
if (!l_obj.haskey(key)) { ; if the key is not already in use
l_obj[key] := value
}
}
}
return l_obj
}
findKey(param_collection,param_predicate,param_fromindex:=1) {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_predicate, param_collection)
if (shorthand != false) {
param_predicate := this._internal_createShorthandfn(param_predicate, param_collection)
}
; create
for key, value in param_collection {
if (param_fromindex > A_Index) {
continue
}
; functor
if (this.isCallable(param_predicate)) {
if (param_predicate.call(value)) {
return key
}
}
}
return false
}
invert(param_object) {
if (!isObject(param_object)) {
this._internal_ThrowException()
}
; prepare
l_obj := this.cloneDeep(param_object)
l_newObj := {}
; create
for key, value in l_obj {
l_newObj[value] := key
}
return l_newObj
}
invertBy(param_object,param_iteratee:="__identity") {
if (!isObject(param_object)) {
this._internal_ThrowException()
}
; prepare
l_obj := this.cloneDeep(param_object)
l_newObj := {}
; create
for key, value in l_obj {
if (this.isCallable(param_iteratee)) {
vkey := param_iteratee.call(value)
} else {
vkey := value
}
if (!isObject(l_newObj[vkey])) {
l_newObj[vkey] := []
}
l_newObj[vkey].push(key)
}
return l_newObj
}
keys(param_object) {
; prepare
if (!isObject(param_object)) {
param_object := StrSplit(param_object)
}
l_returnkeys := []
; create
for key, _ in param_object {
l_returnkeys.push(key)
}
return l_returnkeys
}
mapKeys(param_object,param_iteratee:="__identity") {
if (!isObject(param_object)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_iteratee, param_object)
if (shorthand == ".property") {
param_iteratee := this.property(param_iteratee)
}
if (this.startsWith(param_iteratee.name, this.base.__Class ".")) { ;if starts with "biga."
param_iteratee := param_iteratee.bind(this)
}
l_object := this.cloneDeep(param_object)
l_array := {}
; create
for key, value in l_object {
if (param_iteratee == "__identity") {
l_array[value] := A_Index
continue
}
; functor
if (this.isCallable(param_iteratee)) {
l_array[param_iteratee.call(value, key, l_object)] := A_Index
}
}
return l_array
}
mapValues(param_object,param_iteratee:="__identity") {
if (!isObject(param_object)) {
this._internal_ThrowException()
}
; prepare
shorthand := this._internal_differenciateShorthand(param_iteratee, param_object)
if (shorthand == ".property") {
param_iteratee := this.property(param_iteratee)
}
if (this.startsWith(param_iteratee.name, this.base.__Class ".")) { ;if starts with "biga."
param_iteratee := param_iteratee.bind(this)
}
l_object := this.cloneDeep(param_object)
l_array := {}
; create
for key, value in l_object {
if (param_iteratee == "__identity") {
l_array[key] := value
continue
}
; functor function
if (this.isCallable(param_iteratee)) {
l_array[key] := param_iteratee.call(value, key, l_object)
}
}
return l_array
}
merge(param_collections*) {
if (!isObject(param_collections)) {
this._internal_ThrowException()
}
result := param_collections[1]
for index, obj in param_collections {
if(A_Index = 1) {
continue
}
result := this.internal_Merge(result, obj)
}
return result
}
internal_Merge(param_collection1, param_collection2) {
if(!isObject(param_collection1) && !isObject(param_collection2)) {
; if only one OR the other exist, display them together.
if(param_collection1 = "" || param_collection2 = "") {
return param_collection2 param_collection1
}
; return only one if they are the same
if (param_collection1 = param_collection2)
return param_collection1
; otherwise, return them together as an object.
return [param_collection1, param_collection2]
}
; initialize an associative array
combined := {}
for key, value in param_collection1 {
combined[key] := this.internal_Merge(value, param_collection2[key])
}
for key, value in param_collection2 {
if(!combined.haskey(key)) {
combined[key] := value
}
}
return combined
}
omit(param_object,param_paths) {
if (!isObject(param_object)) {
this._internal_ThrowException()
}
; prepare
l_obj := this.cloneDeep(param_object)
; create
if (isObject(param_paths)) {
for key, value in param_paths {
l_obj.delete(value)
}
} else {
l_obj.delete(param_paths)
}
return l_obj
}
pick(param_object,param_paths) {
if (!isObject(param_object)) {
this._internal_ThrowException()
}
; prepare
l_obj := {}
; create
if (isObject(param_paths)) {
for key, value in param_paths {
vvalue := this.internal_property(value, param_object)
l_obj[value] := vvalue
}
} else {
vvalue := this.internal_property(param_paths, param_object)
l_obj[param_paths] := vvalue
}
return l_obj
}
toPairs(param_object) {
if (!isObject(param_object)) {
this._internal_ThrowException()
}
l_array := []
for key, value in param_object {
l_array.push([key, value])
}
return l_array
}
camelCase(param_string:="") {
if (!this.isStringLike(param_string)) {
this._internal_ThrowException()
}
; prepare
l_arr := this.compact(this.split(param_string, "/[_ -]+/"))
l_head := this.toLower(this.head(l_arr))
; create
l_tail := this.join(this.map(this.tail(l_arr), this.startCase), "")
return l_head l_tail
}
endsWith(param_string,param_needle,param_fromIndex:=0) {
if (!this.isString(param_string) || !this.isString(param_needle) || !this.isNumber(param_fromIndex)) {
this._internal_ThrowException()
}
; prepare defaults
if (param_fromIndex == 0) {
param_fromIndex := StrLen(param_string)
}
if (StrLen(param_needle) > 1) {
param_fromIndex := StrLen(param_string) - StrLen(param_needle) + 1
}
; create
l_endChar := SubStr(param_string, param_fromIndex, StrLen(param_needle))
if (this.isEqual(l_endChar, param_needle)) {
return true
}
return false
}
escape(param_string:="") {
if (!this.isStringLike(param_string)) {
this._internal_ThrowException()
}
; prepare
HTMLmap := [["&","&amp;"], ["<","&lt;"], [">","&gt;"], ["""","&quot;"], ["'","&#39;"]]
for key, value in HTMLmap {
element := value
param_string := StrReplace(param_string, element.1, element.2, , -1)
}
return param_string
}
kebabCase(param_string:="") {
if (!this.isStringLike(param_string)) {
this._internal_ThrowException()
}
; create
l_string := this.startCase(param_string)
l_string := StrReplace(l_string, " ", "-")
return l_string
}
lowerCase(param_string:="") {
if (!this.isStringLike(param_string)) {
this._internal_ThrowException()
}
; create
l_string := this.startCase(param_string)
l_string := this.toLower(this.trim(l_string))
return l_string
}
pad(param_string:="",param_length:=0,param_chars:=" ") {
if (!this.isStringLike(param_string) || !this.isNumber(param_length) || !this.isStringLike(param_chars)) {
this._internal_ThrowException()
}
; prepare
if (param_length <= strLen(param_string)) {
return param_string
}
param_length := param_length - strLen(param_string)
l_start := this.floor(param_length / 2)
l_end := this.ceil(param_length / 2)
; create
l_start := this.padStart("", l_start, param_chars)
l_end := this.padEnd("", l_end, param_chars)
return l_start param_string l_end
}
padEnd(param_string:="",param_length:=0,param_chars:=" ") {
if (!this.isStringLike(param_string) || !this.isNumber(param_length) || !this.isStringLike(param_chars)) {
this._internal_ThrowException()
}
; prepare
if (param_length <= strLen(param_string)) {
return param_string
}
; create
l_pad := this.slice(param_chars)
l_string := param_string
while (strLen(l_string) < param_length) {
l_pos++
if (l_pos > l_pad.count()) {
l_pos := 1
}
l_string .= l_pad[l_pos]
}
return l_string
}
padStart(param_string:="",param_length:=0,param_chars:=" ") {
if (!this.isStringLike(param_string) || !this.isNumber(param_length) || !this.isStringLike(param_chars)) {
this._internal_ThrowException()
}
; prepare
if (param_length <= strLen(param_string)) {
return param_string
}
; create
l_pad := this.slice(param_chars)
while (strLen(param_string) + strLen(l_padding) < param_length) {
l_pos++
if (l_pos > l_pad.count()) {
l_pos := 1
}
l_padding .= l_pad[l_pos]
}
return l_padding . param_string
}
parseInt(param_string:="0") {
if (!this.isStringLike(param_string)) {
this._internal_ThrowException()
}
; prepare
l_int := this.trimStart(param_string, " 0_")
; create
if (this.size(l_int) == 0 && inStr(param_string, "0")) {
return 0
}
if (this.isNumber(l_int)) {
return l_int
}
l_int := this.replace(l_int, "/\D+/")
if (this.isNumber(l_int)) {
return l_int
}
return ""
}
repeat(param_string,param_number:=1) {
if (!this.isString(param_string) || (!this.isNumber(param_number))) {
this._internal_ThrowException()
}
if (param_number == 0) {
return ""
}
return StrReplace(Format("{:0" param_number "}", 0), "0", param_string)
}
replace(param_string:="",param_needle:="",param_replacement:="") {
if (!this.isStringLike(param_string) || !this.isStringLike(param_needle) || !this.isStringLike(param_replacement)) {
this._internal_ThrowException()
}
; prepare
l_string := param_string
; create
if (l_needle := this._internal_JSRegEx(param_needle)) {
return RegExReplace(param_string, l_needle, param_replacement, , this.limit)
}
output := StrReplace(l_string, param_needle, param_replacement, , this.limit)
return output
}
snakeCase(param_string:="") {
if (!this.isStringLike(param_string)) {
this._internal_ThrowException()
}
; create
l_string := this.startCase(param_string)
l_string := StrReplace(l_string, " ", "_")
return l_string
}
split(param_string:="",param_separator:=",",param_limit:=0) {
if (!this.isStringLike(param_string) || !this.isStringLike(param_separator) || !this.isNumber(param_limit)) {
this._internal_ThrowException()
}
; prepare inputs if regex detected
if (this._internal_JSRegEx(param_separator)) {
param_string := this.replace(param_string, param_separator, ",")
param_separator := ","
}
; create
oSplitArray := strSplit(param_string, param_separator)
if (!param_limit) {
return oSplitArray
} else {
oReducedArray := []
loop, % param_limit {
if (A_Index <= oSplitArray.count()) {
oReducedArray.push(oSplitArray[A_Index])
}
}
}
return oReducedArray
}
startCase(param_string:="") {
if (!this.isStringLike(param_string)) {
this._internal_ThrowException()
}
; create
l_string := this.replace(param_string, "/[_ -]/", " ")
; add space before each capitalized character
RegExMatch(l_string, "O)([A-Z])", RE_Match)
if (RE_Match.count()) {
loop, % RE_Match.count() {
l_string := % SubStr(l_string, 1, RE_Match.Pos(A_Index) - 1) " " SubStr(l_string, RE_Match.Pos(A_Index))
}
}
; Split the string into array and Titlecase each element in the array
l_array := StrSplit(l_string, " ")
loop, % l_array.count() {
l_string := l_array[A_Index]
StringUpper, l_string, l_string, T
l_array[A_Index] := l_string
}
; join the string back together from Titlecased array elements
l_string := this.join(l_array, " ")
l_string := trim(l_string)
return l_string
}
startsWith(param_string,param_needle,param_fromIndex:=1) {
if (!this.isStringLike(param_string) || !this.isStringLike(param_needle) || !this.isNumber(param_fromIndex)) {
this._internal_ThrowException()
}
; create
l_startString := subStr(param_string, param_fromIndex, strLen(param_needle))
; check if substring matches
if (this.isEqual(l_startString, param_needle)) {
return true
}
return false
}
toLower(param_string) {
if (!this.isString(param_string)) {
this._internal_ThrowException()
}
; create
StringLower, OutputVar, param_string
return OutputVar
}
toUpper(param_string) {
if (!this.isString(param_string)) {
this._internal_ThrowException()
}
; create
StringUpper, OutputVar, param_string
return OutputVar
}
trim(param_string,param_chars:="") {
if (!this.isStringLike(param_string) || !this.isStringLike(param_chars)) {
this._internal_ThrowException()
}
; create
if (param_chars == "") {
return trim(param_string)
} else {
; replace starting characters
l_string := this.trimStart(param_string, param_chars)
; replace ending characters
l_string := this.trimEnd(l_string, param_chars)
return l_string
}
}
trimEnd(param_string,param_chars:="") {
if (!this.isStringLike(param_string) || !this.isStringLike(param_chars)) {
this._internal_ThrowException()
}
; create
if (param_chars = "") {
l_string := param_string
return regexreplace(l_string, "(\s+)$") ;trim ending whitespace
} else {
l_array := StrSplit(param_chars, "")
for key, value in l_array {
if (this.includes(value, "/[a-zA-Z0-9]/")) {
l_removechars .= value
} else {
l_removechars .= "\" value
}
}
; replace ending characters
l_string := this.replace(param_string, "/([" l_removechars "]+)$/", "")
return l_string
}
}
trimStart(param_string,param_chars:="") {
if (!this.isStringLike(param_string) || !this.isStringLike(param_chars)) {
this._internal_ThrowException()
}
; create
if (param_chars = "") {
return regexreplace(param_string, "^(\s+)") ;trim beginning whitespace
} else {
l_array := StrSplit(param_chars, "")
for key, value in l_array {
if (this.includes(value, "/[a-zA-Z0-9]/")) {
l_removechars .= value
} else {
l_removechars .= "\" value
}
}
; replace leading characters
l_string := this.replace(param_string, "/^([" l_removechars "]+)/", "")
return l_string
}
}
truncate(param_string,param_options:="") {
if (!this.isString(param_string)) {
this._internal_ThrowException()
}
; prepare
if (!isObject(param_options)) {
param_options := {}
param_options.length := 30
}
if (!param_options.haskey("omission")) {
param_options.omission := "..."
}
; check that length is even worth working on, skip if separator is defined
if (strLen(param_string) < param_options.length && !param_options.separator) {
return param_string
}
; create
; cut length of the string by character count + the omission's length
l_string := subStr(param_string, 1, param_options.length)
; Regex separator
if (this._internal_JSRegEx(param_options.separator)) {
param_options.separator := this._internal_JSRegEx(param_options.separator)
}
; handle string or Regex seperator
if (param_options.separator) {
return RegexReplace(l_string, "^(.{1," param_options.length "})" param_options.separator ".*$", "$1") param_options.omission
}
; omission
if (strLen(l_string) < strLen(param_string)) {
l_string := subStr(l_string, 1, (strLen(l_string) - strLen(param_options.omission) + 1))
l_string := l_string . param_options.omission
}
return l_string
}
unescape(param_string:="") {
if (!this.isStringLike(param_string)) {
this._internal_ThrowException()
}
; prepare
HTMLmap := [["&","&amp;"], ["<","&lt;"], [">","&gt;"], ["""","&quot;"], ["'","&#39;"]]
for key, value in HTMLmap {
element := value
param_string := StrReplace(param_string, element.2, element.1, , -1)
}
return param_string
}
upperCase(param_string:="") {
if (!this.isStringLike(param_string)) {
this._internal_ThrowException()
}
; create
l_string := this.startCase(param_string)
l_string := this.toupper(this.trim(l_string))
return l_string
}
words(param_string,param_pattern:="/[^\W]+/") {
if (!this.isString(param_string) || !this.isString(param_pattern)) {
this._internal_ThrowException()
}
l_string := param_string
l_array := []
if (l_needle := this._internal_JSRegEx(param_pattern)) {
param_pattern := l_needle
}
l_needle := "O)" param_pattern
while(RegExMatch(l_string, l_needle, RE_Match)) {
tempString := RE_Match.value()
l_array.push(tempString)
l_string := SubStr(l_string, RE_Match.Pos()+RE_Match.Len())
}
return l_array
}
constant(param_value) {
boundFunc := ObjBindMethod(this, "_internal_constant", param_value)
return boundFunc
}
_internal_constant(param_value) {
return param_value
}
matches(param_source) {
if (!isObject(param_source)) {
this._internal_ThrowException()
}
boundFunc := ObjBindMethod(this, "internal_matches", param_source)
return boundFunc
}
internal_matches(param_matches,param_itaree) {
for key, value in param_matches {
if (param_matches[key] != param_itaree[key]) {
return false
}
}
return true
}
matchesProperty(param_path,param_srcvalue) {
if (!this.isStringLike(param_srcvalue)) {
this._internal_ThrowException()
}
; create the property fn
fnProperty := this.property(param_path)
; create the fn
boundFunc := ObjBindMethod(this, "_internal_matchesProperty", fnProperty, param_srcvalue)
return boundFunc
}
_internal_matchesProperty(param_property,param_matchvalue,param_itaree) {
itareevalue := param_property.call(param_itaree)
; msgbox, % "comparing " this._printObj(param_matchvalue) " to " this._printObj(itareevalue) " from(" this._printObj(param_itaree) ")"
if (!this.isUndefined(itareevalue)) {
if (itareevalue = param_matchvalue) {
return true
}
}
return false
}
property(param_source) {
; prepare
if (this.includes(param_source, ".")) {
param_source := strSplit(param_source, ".")
}
; create the fn
if (isObject(param_source)) {
keyArray := []
for key, value in param_source {
keyArray.push(value)
}
boundFunc := ObjBindMethod(this, "internal_property", keyArray)
return boundFunc
} else {
boundFunc := ObjBindMethod(this, "internal_property", param_source)
return boundFunc
}
}
internal_property(param_property,param_itaree) {
if (isObject(param_property)) {
for key, value in param_property {
if (param_property.count() == 1) {
; msgbox, % "dove deep and found: " ObjRawGet(param_itaree, value)
return ObjRawGet(param_itaree, value)
} else if (param_itaree.haskey(value)){
rvalue := this.internal_property(this.tail(param_property), param_itaree[value])
}
}
return rvalue
}
return param_itaree[param_property]
}
times(param_n,param_iteratee:="__identity") {
if (!this.isNumber(param_n)) {
this._internal_ThrowException()
}
; prepare
if (this.startsWith(param_iteratee.name, this.base.__Class ".")) { ;if starts with "biga."
guarded := this.includes(this._guardedMethods, strSplit(param_iteratee.name, ".").2)
param_iteratee := param_iteratee.bind(this)
}
shorthand := this._internal_differenciateShorthand(param_iteratee)
if (shorthand != false) {
param_iteratee := this._internal_createShorthandfn(param_iteratee)
}
l_array := []
; create
loop, % param_n {
l_array.push(param_iteratee.call(A_Index))
}
return l_array
}
first(param_array) {
; create
return this.take(param_array)[1]
}
each(param_collection,param_iteratee:="__identity") {
if (!isObject(param_collection)) {
this._internal_ThrowException()
}
; prepare
if (!isFunc(param_iteratee)) {
boundFunc := param_iteratee.bind(this)
}
if (l_paramAmmount == 3) {
collectionClone := this.cloneDeep(param_collection)
}
; create
; run against every value in the collection
for key, value in param_collection {
if (!boundFunc) { ; is property/string
;nothing currently
}
if (!boundFunc.call(value, key, collectionClone)) {
vIteratee := param_iteratee.call(value, key, collectionClone)
}
; exit iteration early by explicitly returning false
if (vIteratee == false) {
return param_collection
}
}
return param_collection
}
entries(param_object) {
if (!isObject(param_object)) {
this._internal_ThrowException()
}
l_array := []
for key, value in param_object {
l_array.push([key, value])
}
return l_array
}
}
class A extends biga {
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment