Module:ArrayList
Appearance
From Wikipedia, the free encyclopedia
You might want to create a documentation page for this Scribunto module.
Editors can experiment in this module's sandbox (create | mirror) and testcases (create) pages.
Add categories to the /doc subpage. Subpages of this module.
Editors can experiment in this module's sandbox (create | mirror) and testcases (create) pages.
Add categories to the /doc subpage. Subpages of this module.
localp={} -- Helper function to trim whitespace localfunctiontrim(s) returns:match("^%s*(.-)%s*$") end -- Escape special characters in the delimiter for pattern matching localfunctionescapePattern(str) returnstr:gsub("([%^%$%(%)%%%.%[%]%*%+%?%-])","%%%1") end -- Main function to call other functions dynamically functionp.main(frame) localfunc=frame.args[1] ifp[func]then returnp[func](frame) else return"void:notfound "..tostring(func) end end -- Count occurrences of delimiter in a string functionp.count(frame) localstr=frame.args[2]or"" localdelimiter=frame.args[3]or"," localnostrip=frame.args["nostrip"] delimiter=escapePattern(delimiter) -- If nostrip is not set to "true", strip leading/trailing delimiters ifnostrip~="true"then -- Remove leading and trailing delimiters (along with any surrounding whitespace) str=str:gsub("^%s*"..delimiter.."%s*",""):gsub("%s*"..delimiter.."%s*$","") -- Normalize internal consecutive delimiters to a single delimiter (replace ",," with ",") str=str:gsub("%s*"..delimiter.."%s*"..delimiter.."%s*",delimiter) end localcount=select(2,str:gsub(delimiter,"")) returncount+1 end -- Get the Nth item in a delimited string, supporting negative indices functionp.get(frame) localstr=frame.args[2]or"" localdelimiter=frame.args[3]or"," localindex=frame.args[4] delimiter=escapePattern(delimiter) str=str:gsub("^%s*"..delimiter.."%s*(.-)%s*"..delimiter.."$","%1") localitems={} foriteminstring.gmatch(str,"([^"..delimiter.."]+)")do table.insert(items,trim(item)) end ifindex=="last"then index=#items elseifindexandtonumber(index)then index=tonumber(index) ifindex<0then index=#items+index+1 end else return"void:invalid" end returnitems[index]or"void:outrange" end -- Find the position of the Nth occurrence of a matching item in a delimited string functionp.pos(frame) localstr=frame.args[2]or"" localdelimiter=frame.args[3]or"," localitem=frame.args[4]or"" localoccurrence=tonumber(frame.args[5]) delimiter=escapePattern(delimiter) str=str:gsub("^%s*"..delimiter.."%s*(.-)%s*"..delimiter.."$","%1") localpositions={} localindex=1 forsubiteminstring.gmatch(str,"([^"..delimiter.."]+)")do subitem=trim(subitem) ifsubitem==itemthen table.insert(positions,index) end index=index+1 end ifnotoccurrencethen return#positions>0andtable.concat(positions,",")or"void:nomatch" else returnpositions[occurrence]or-1 end end -- Perform mathematical operations on numeric array items functionp.math(frame) localstr=frame.args[2]or"" localdelimiter=frame.args[3]or"," localoperation=frame.args[4] delimiter=escapePattern(delimiter) str=str:gsub("^%s*"..delimiter.."%s*(.-)%s*"..delimiter.."$","%1") localitems={} foriteminstring.gmatch(str,"([^"..delimiter.."]+)")do localnumber=tonumber(trim(item)) ifnumberthen table.insert(items,number) else return"void:isalpha" end end if#items==0then return"void:nonumeric" elseifoperation=="sum"then localtotal=0 for_,numinipairs(items)do total=total+num end returntotal elseifoperation=="min"oroperation=="max"then localextreme=items[1] localcomparison=operation=="min"andfunction(a,b)returna<bendorfunction(a,b)returna>bend for_,numinipairs(items)do ifcomparison(num,extreme)then extreme=num end end returnextreme else return"void:unsupported" end end -- Sorts array with options for reverse ("r") and alpha-first ("a"). functionp.sort(frame) localstr=frame.args[2]or"" localdelimiter=frame.args[3]or"," localparams=frame.args[4]or"" localdelim_pat=escapePattern(delimiter) -- Determine sort options (check if params a or r expressed) localreverse=params:find("r")andtrueorfalse localalpha_priority=params:find("a")andtrueorfalse localitems={} localorig_index=1 -- Split string using delimiter. foriteminstring.gmatch(str,"([^"..delim_pat.."]+)")do item=item:match("^%s*(.-)%s*$")-- trim whitespace localnum=tonumber(item) localisnum=(num~=nil) localisalpha=(notisnumanditem:match("^[A-Za-z]+$"))andtrueorfalse localgroup ifalpha_prioritythen ifisalphathen group=1 elseifisnumthen group=2 else group=3 end else ifisnumthen group=1 elseifisalphathen group=2 else group=3 end end table.insert(items,{ raw=item, num=num, isnum=isnum, isalpha=isalpha, group=group, orig=orig_index-- remember original order for special items }) orig_index=orig_index+1 end table.sort(items,function(a,b) -- compare groups ifa.group~=b.groupthen returna.group<b.group end -- if both items in same group, decide -- comparison based on alpha_priority flag ifalpha_prioritythen -- if letters come first, group 1 = letters ifa.group==1then-- Both are alphabetic. returna.raw:lower()<b.raw:lower() elseifa.group==2then-- Both are numeric. returna.num<b.num else-- Group 3: special items. returna.orig<b.orig end else -- if numbers first, group 1 = numbers ifa.group==1then-- Both are numeric. returna.num<b.num elseifa.group==2then-- Both are alphabetic. returna.raw:lower()<b.raw:lower() else-- Group 3: special items. returna.orig<b.orig end end end) -- Reverse order if requested ifreversethen fori=1,math.floor(#items/2)do items[i],items[#items-i+1]=items[#items-i+1],items[i] end end -- Build output string localoutput={} for_,vinipairs(items)do table.insert(output,v.raw) end returntable.concat(output,delimiter) end returnp