跳转到内容

Module:TableTools

维基教科书,自由的教学读本

此模块的文档可以在Module:TableTools/doc创建

-------------------------------------------------------------------------------------- TableTools ---- ---- This module includes a number of functions for dealing with Lua tables. ---- It is a meta-module, meant to be called from other Lua modules, and should ---- not be called directly from #invoke. ----------------------------------------------------------------------------------------]]locallibraryUtil=require('libraryUtil')localp={}-- Define often-used variables and functions.localfloor=math.floorlocalinfinity=math.hugelocalcheckType=libraryUtil.checkType--[[-------------------------------------------------------------------------------------- isPositiveInteger---- This function returns true if the given value is a positive integer, and false-- if not. Although it doesn't operate on tables, it is included here as it is-- useful for determining whether a given table key is in the array part or the-- hash part of a table.--------------------------------------------------------------------------------------]]functionp.isPositiveInteger(v)iftype(v)=='number'andv>=1andfloor(v)==vandv<infinitythenreturntrueelsereturnfalseendend--[[-------------------------------------------------------------------------------------- isNan---- This function returns true if the given number is a NaN value, and false-- if not. Although it doesn't operate on tables, it is included here as it is-- useful for determining whether a value can be a valid table key. Lua will-- generate an error if a NaN is used as a table key.--------------------------------------------------------------------------------------]]functionp.isNan(v)iftype(v)=='number'andtostring(v)=='-nan'thenreturntrueelsereturnfalseendend--[[-------------------------------------------------------------------------------------- shallowClone---- This returns a clone of a table. The value returned is a new table, but all-- subtables and functions are shared. Metamethods are respected, but the returned-- table will have no metatable of its own.--------------------------------------------------------------------------------------]]functionp.shallowClone(t)localret={}fork,vinpairs(t)doret[k]=vendreturnretend--[[-------------------------------------------------------------------------------------- removeDuplicates---- This removes duplicate values from an array. Non-positive-integer keys are-- ignored. The earliest value is kept, and all subsequent duplicate values are-- removed, but otherwise the array order is unchanged.--------------------------------------------------------------------------------------]]functionp.removeDuplicates(t)checkType('removeDuplicates',1,t,'table')localisNan=p.isNanlocalret,exists={},{}fori,vinipairs(t)doifisNan(v)then-- NaNs can't be table keys, and they are also unique, so we don't need to check existence.ret[#ret+1]=velseifnotexists[v]thenret[#ret+1]=vexists[v]=trueendendendreturnretend--[[-------------------------------------------------------------------------------------- numKeys---- This takes a table and returns an array containing the numbers of any numerical-- keys that have non-nil values, sorted in numerical order.--------------------------------------------------------------------------------------]]functionp.numKeys(t)checkType('numKeys',1,t,'table')localisPositiveInteger=p.isPositiveIntegerlocalnums={}fork,vinpairs(t)doifisPositiveInteger(k)thennums[#nums+1]=kendendtable.sort(nums)returnnumsend--[[-------------------------------------------------------------------------------------- affixNums---- This takes a table and returns an array containing the numbers of keys with the-- specified prefix and suffix. For example, for the table-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will-- return {1, 3, 6}.--------------------------------------------------------------------------------------]]functionp.affixNums(t,prefix,suffix)checkType('affixNums',1,t,'table')checkType('affixNums',2,prefix,'string',true)checkType('affixNums',3,suffix,'string',true)localfunctioncleanPattern(s)-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.s=s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])','%%%1')returnsendprefix=prefixor''suffix=suffixor''prefix=cleanPattern(prefix)suffix=cleanPattern(suffix)localpattern='^'..prefix..'([1-9]%d*)'..suffix..'$'localnums={}fork,vinpairs(t)doiftype(k)=='string'thenlocalnum=mw.ustring.match(k,pattern)ifnumthennums[#nums+1]=tonumber(num)endendendtable.sort(nums)returnnumsend--[[-------------------------------------------------------------------------------------- numData---- Given a table with keys like ("foo1", "bar1", "foo2", "baz2"), returns a table-- of subtables in the format -- { [1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'} }-- Keys that don't end with an integer are stored in a subtable named "other".-- The compress option compresses the table so that it can be iterated over with-- ipairs.--------------------------------------------------------------------------------------]]functionp.numData(t,compress)checkType('numData',1,t,'table')checkType('numData',2,compress,'boolean',true)localret={}fork,vinpairs(t)dolocalprefix,num=mw.ustring.match(tostring(k),'^([^0-9]*)([1-9][0-9]*)$')ifnumthennum=tonumber(num)localsubtable=ret[num]or{}ifprefix==''then-- Positional parameters match the blank string; put them at the start of the subtable instead.prefix=1endsubtable[prefix]=vret[num]=subtableelselocalsubtable=ret.otheror{}subtable[k]=vret.other=subtableendendifcompressthenlocalother=ret.otherret=p.compressSparseArray(ret)ret.other=otherendreturnretend--[[-------------------------------------------------------------------------------------- compressSparseArray---- This takes an array with one or more nil values, and removes the nil values-- while preserving the order, so that the array can be safely traversed with-- ipairs.--------------------------------------------------------------------------------------]]functionp.compressSparseArray(t)checkType('compressSparseArray',1,t,'table')localret={}localnums=p.numKeys(t)for_,numinipairs(nums)doret[#ret+1]=t[num]endreturnretend--[[-------------------------------------------------------------------------------------- sparseIpairs---- This is an iterator for sparse arrays. It can be used like ipairs, but can-- handle nil values.--------------------------------------------------------------------------------------]]functionp.sparseIpairs(t)checkType('sparseIpairs',1,t,'table')localnums=p.numKeys(t)locali=0locallim=#numsreturnfunction()i=i+1ifi<=limthenlocalkey=nums[i]returnkey,t[key]elsereturnnil,nilendendend--[[-------------------------------------------------------------------------------------- size---- This returns the size of a key/value pair table. It will also work on arrays,-- but for arrays it is more efficient to use the # operator.--------------------------------------------------------------------------------------]]functionp.size(t)checkType('size',1,t,'table')locali=0forkinpairs(t)doi=i+1endreturniendreturnp
close