The more generic, the more useful.
[lua]
function utilx.find(t, func)
local matches = {}
for k,v in pairs(t) do
if func(v) then
table.insert(matches, v)
end
end
return matches
end
[/lua]
[lua]
for k,v in pairs(utilx.find(player.GetAll(), function(p) return string.match(p:Nick(), "Ownage96") end)) do
print(v:Nick().." is a cactus.")
end
[/lua]
[b]Edit:[/b] Thanks, Tobba
if matches(v) then
Don't you mean to use func there?
For those of you who didn't see it in the WAYWO thread:
[url]http://entoros.pastebin.com/z8W13euC[/url]
Here's my helper function for finding players:
[lua]function findTarget(plyID)
if type(plyID) == "string" then
local isSteamID = string.match(plyID, "^STEAM_")
for _, v in ipairs(player.GetAll()) do
if ValidEntity(v) then
if isSteamID then
if v:SteamID() == plyID then return v end
else
local name = string.lower(plyID)
if v:UniqueID() == plyID
|| string.match(string.lower(v:GetName()), name) then return v end
end
end
end
elseif type(plyID) == "number" then
local ply = Player(plyID)
if ValidEntity(ply) then return ply end
end
end[/lua]
I'm not sure if this has been posted yet, but whatever. A simple function to flip teams with an option of killsilent and a default team for any other teams to switch to. This would be better in the team library in my opinion.
[lua]
function utilx.FlipTeams( teamID1, teamID2, teamDefault, bKill )
for _, ply in pairs( player.GetAll() ) do
if IsValid(ply) then
local couldKill = true
if teamDefault then
ply:SetTeam( teamDefault )
elseif ply:Team() == teamID1 then
ply:SetTeam( teamID2 )
elseif ply:Team() == teamID2 then
ply:SetTeam( teamID1 )
else
couldKill = false
end
if bKill and couldKill and ply:Alive() then
ply:KillSilent()
end
end
end
end[/lua]
I don't know if this has been done already but it's same as expression2s findPlayerByName function.
[code]
function utilx.FindPlayerByName(stringname)
for k,v in pairs(player.GetAll()) do
if v:Name() == stringname then
return v
end
end
end
[/code]
[lua]
function util.PrecacheTableRecursive( t )
for k, v in pairs( t ) do
if type(v) == "table" then
util.PrecacheTableRecursive( v )
elseif type(v) == "string" then
local ext = v:sub( -4 )
local isValidSound = (ext == ".wav" or ext == ".mp3")
local isValidModel = (ext == ".mdl" and util.IsValidModel(v))
if isValidSound then
util.PrecacheSound( v )
elseif isValidModel then
util.PrecacheModel( v )
else
print( "Attempted to precache '"..tostring(v).."' which is not a valid "..((isValidSound and "sound") or (isValidModel and "model") or "string")..". Skipping..." )
end
else
print( "Attempted to precache '"..tostring(v).."' which is not a valid string. Skipping..." )
end
end
end
[/lua]
Recursively precaches a table of sounds and/or models. Might need some tweaking.
[QUOTE=grea$emonkey;25658381][lua]
function util.PrecacheTableRecursive( t )
for k, v in pairs( t ) do
if type(v) == "table" then
util.PrecacheTableRecursive( v )
elseif type(v) == "string" then
local ext = v:sub( -4 )
local isValidSound = (ext == ".wav" or ext == ".mp3")
local isValidModel = (ext == ".mdl" and util.IsValidModel(v))
if isSound then
util.PrecacheSound( v )
elseif isModel then
util.PrecacheModel( v )
else
print( "Attempted to precache '"..tostring(v).."' which is not a valid "..((isSound and "sound") or isModel and "model")..". Skipping..." )
end
else
print( "Attempted to precache '"..tostring(v).."' which is not a valid string. Skipping..." )
end
end
end
[/lua]
Recursively precaches a table of sounds and/or models. Might need some tweaking.[/QUOTE]
Looks great. Is there anything in here that can match a table value like when you do table.remove(k) to the string/entity that's in the table? This is from 2 different tables.
[QUOTE=grea$emonkey;25658381]-code-
Recursively precaches a table of sounds and/or models. Might need some tweaking.[/QUOTE]
You're using isSound and isModel, but you've only defined isValidSound and isValidModel.
[QUOTE=raBBish;25658584]You're using isSound and isModel, but you've only defined isValidSound and isValidModel.[/QUOTE]
Oops, haha my bad.
[editline]26th October 2010[/editline]
Fixed. Like I said, may need tweaking.
Couple functions I made when I was bored (inspired by Ruby)
Unfortunately they both only support tables with numbered tables.
[lua]function utilx.TableFlatten( tbl, new )
new = new or {}
for k,v in ipairs( tbl ) do
if type( v ) == "table" then
utilx.TableFlatten( v, new )
else
table.insert( new, v )
end
end
return new
end
function utilx.TableUnique( tbl )
local new = {}
local done = {}
for k,v in ipairs( tbl ) do
if not done[v] then
table.insert( new, v )
done[v] = true
end
end
return new
end[/lua]
[url]http://codepad.org/dhk06oKx[/url]
from the WAYWO thread:
[lua]
function utilx.Check(variable, ...)
local name = debug.getinfo(2, "n").name
local func = debug.getinfo(2, "f").func
local types = {...}
local allowed = ""
local matched = false
for key, value in ipairs(types) do
if #types ~= key then
allowed = allowed .. value .. " or "
else
allowed = allowed .. value
end
if type(variable) == value then
matched = true
end
end
local arg = "???"
for i=1, math.huge do
local key, value = debug.getlocal(2, i)
if not key then break end
if value == variable then
arg = i
break end
end
if not matched then
error(("bad argument #%s to '%s' (%s expected, got %s)"):format(arg, name, allowed, type(typ)), 3)
end
end
[/lua]
[lua]
function Hello( str, entity, hello )
utilx.Check(str, "string")
utilx.Check(entity, "Entity")
utilx.Check(hello, "Player", "Entity")
end
Hello("hey", Entity(3), Entity(1))
[/lua]
output goes like this:
[code]
[@addons\autorun\lua\check.lua:42] bad argument #2 to 'Hello' (Entity expected, got Player)
[@addons\autorun\lua\check.lua:42] bad argument #3 to 'Hello' (Player or Entity expected, got nil)
[/code]
if the arg types are wrong in Hello
The only problem with this is getting the local from the function you're checking and matching it against the variable in the check function. If you are calling a function with the number "5" in two args, and the second arg is wrong it will pick the first arg that matches that value and say arg #1 is wrong instead of #2.
[lua]
function utilx.Crash(ply)
ply:SendLua"cam.End3D()"
end
[/lua]
:downs:
Add overloading to lua.
[lua]
--[[
local tblTest = {
[{"string","number","player"}] = function (strName,numID,objPl) end,
[{"string","table"}] = function (strName,tbl) end,
[{"string","number"}] = function (strName,num) end
}
local tblOptimized = {
["string"] = {
["number"] = {
["player"] = funcCallback,
["nil"] = funcCallback
},
["table"] = funcCallback
}
}
how it gets the function:
tblOptimized["string"]["number"]["player"](str,num,pl, ...) --accumulated/dissipated table accessing ofcourse (or it would probably error)
]]
function Overload(tblSetup,funcDefault_or_bNoDefault)
local tblOverload = {}
for tblParams, funcCallback in pairs(tblSetup) do
local tblCurrent = tblOverload
for i=1, #tblParams do
local strType = tblParams[i]
tblCurrent[strType] = tblCurrent[strType] or {}
tblCurrent = tblCurrent[strType]
end
tblCurrent["nil"] = funcCallback
end
if type(funcDefault_or_bNoDefault) == "function" then
return function (...)
local tblParams, tblLast, numParam = {...}, tblOverload, 1
while true do
local strType = type(tblParams[numParam])
local vNext = tblLast[strType]
if type(vNext) == "function" then
local bOk, valReturn = pcall(vNext,...)
if not bOk then
error(valReturn,2)
end
return valReturn
elseif type(vNext) == "table" then
tblLast = tblLast[strType]
numParam = numParam + 1
else
local bOk, valReturn = pcall(funcDefault_or_bNoDefault,...)
if not bOk then
error(valReturn,2)
end
return valReturn
end
end
end
elseif type(funcDefault_or_bNoDefault) == "boolean" and funcDefault_or_bNoDefault then
return function (...)
local tblParams, tblLast, numParam = {...}, tblOverload, 1
while true do
local strType = type(tblParams[numParam])
local vNext = tblLast[strType]
if type(vNext) == "function" then
local bOk, valReturn = pcall(vNext,...)
if not bOk then
error(valReturn,2)
end
return valReturn
elseif type(vNext) == "table" then
tblLast = tblLast[strType]
numParam = numParam + 1
else
local bOk, valReturn = pcall(tblLast["nil"],...)
if not bOk then
error(valReturn,2)
end
return valReturn
end
end
end
end
return function (...)
local tblParams, tblLast, numParam = {...}, tblOverload, 1
while true do
local strType = type(tblParams[numParam])
local vNext = tblLast[strType]
if type(vNext) == "function" then
local bOk, valReturn = pcall(vNext,...)
if not bOk then
error(valReturn,2)
end
return valReturn
elseif type(vNext) == "table" then
tblLast = tblLast[strType]
numParam = numParam + 1
else
return nil
end
end
end
end
[/lua]
I get bored sometimes.
I'm using this in my Trooper Hack, was actually disappointed and surprised at the same time to discover there is no function for this.
[lua]
function utilx.GetPlayerID( ply )
for k,v in pairs ( player.GetAll() ) do
if v == ply then return k end
end
end
[/lua]
Becuse ply:EntIndex() is better, and works perfectly fine
Sorry if there is already something in this like that, but this has been useful to more more than once:
[lua]function utilx.SimplifyPath(Path)
local Array = string.Explode("/", Path)
local NewArray = {}
for _, V in pairs(Array) do
if V == ".." then
if #NewArray == 0 or NewArray[#NewArray] == ".." then
NewArray[#NewArray + 1] = ".."
else
table.remove(NewArray)
end
elseif V != "." then
NewArray[#NewArray + 1] = V
end
end
return table.concat(NewArray, "/")
end[/lua]
Makes "lua/././../test/../help/me/../../../a.lua" into "../a.lua".
Maybe not the most efficient way to do it, but it works :3:.
[QUOTE=iRzilla;26103436]Regular expressions. (Deco fix it.)[/QUOTE]
You mean Lua expressions?
I wish Lua did regex.
[QUOTE=iRzilla;26103436]Regular expressions. (Deco fix it.)[/QUOTE]
Deco and his metapatterns.
Here's an explode function I made which is able to explode around separators larger than 1 character.
*old sucky code* see below for new code
Let me know if you find any way to optimize it. EDIT: Or if you find wrongs or flaws.
Is it faster than string.Explode?
[QUOTE=Overv;26155232]Is it faster than string.Explode?[/QUOTE]
Not sure, but I believe so. Garry uses table.insert as well, which is very slow.
And I just noticed a way to make it better: Add another elseif when the pattern is only 1 character long, and also have a count variable instead of using #ret over and over again. I'll add that when I get home.
EDIT: I just tested it with the Lua Demo page, and it seems to have a small problem... but it could be the temporary string.Left/Right functions I made (since they aren't standard in Lua). I'll have to see what's up with that when I get home, too.
[lua]
function utilx.explode(str, delim, notplain)
notplain = not notplain -- I just confused myself
local res = {}
local newpos, pos, start = 0
repeat
pos = newpos+1
start, newpos = string.find(str, delim, pos, notplain)
res[#res+1] = string.sub(str, pos, (start or 0)-1)
until not start
return res
end
[/lua]
Nicely done. Much better than mine.
EDIT: -snip nvm-
[QUOTE=Divran;26155978]EDIT: Which way is faster: str:find( ... ) or string.find( str, ... ) ?[/QUOTE]
It's the same exact thing..
[QUOTE=Deco Da Man;26155564]-snip-[/QUOTE]
I was trying to rewrite that using gsub/gmatch, then I remembered string sets only work in Regex :arghfist::saddowns:
When I speed tested our functions, yours performed beautifully when exploding around large separators, like entire words. However, when exploding around single character, or empty ("") separators, mine was much faster... So I combined them to get the best of both. I didn't make it able to handle patterns though, like yours could.
[lua]local specialchars = {
["%"] = true,
["^"] = true,
["$"] = true,
["("] = true,
[")"] = true,
["."] = true,
["["] = true,
["]"] = true,
["*"] = true,
["+"] = true,
["-"] = true,
["?"] = true
}
local gmatch = string.gmatch
local sub = string.sub
local Right = string.Right
local find = string.find
function utilx.explode( str, delim )
if (str == "") then return {} end
if (delim == "") then -- Quicker loop for when the delim is empty
local ret = {}
for i=1,#str do
ret[i] = str:sub(i,i)
end
return ret
elseif (#delim == 1) then -- Quicker loop when delim is 1 char
local ret = {}
local _delim, count = delim, 0
if (specialchars[delim]) then delim = "%" .. delim end
for word in str:gmatch( "[^" .. delim .. "]+" ) do
count = count + 1
ret[count] = word
end
return ret
else
local res = {}
local count, newpos, pos, start = 1, 0
repeat
pos = newpos+1
start, newpos = str:find( delim, pos, true )
res[count] = str:sub( pos, (start or 0)-1)
count = count + 1
until not start
return res
end
end[/lua]
[lua]local lpeg = require "lpeg"
function string.split( str, sep )
local sep = lpeg.P( sep )
local txt = lpeg.C( (1-sep) ^ 1 )
local list = lpeg.Ct( txt * (sep * txt)^0 )
return list:match( str ) or {}
end
table.print( ("this is a test"):split " " )[/lua]
[code]1 this
2 is
3 a
4 test[/code]
Dug up LPeg :haw:
[QUOTE=raBBish;26156919]Dug up LPeg :haw:[/QUOTE]
what's that
I though lpeg was broken?
Sorry, you need to Log In to post a reply to this thread.