Page 2 of 2

Re: Hey, so here's a couple functions!

Posted: Wed Dec 14, 2016 12:59 am
by Nicholas Scott
Haha I love what this has become :D, I'm gonna edit the post and add the functions Positive07 did with credit ofc :D but not remove the originals, just in case someone wants them, or when they look at the post they don't get confuzzled haha, Great job by the way Positive, I didn't really focus on optimization or usefulness, I just threw the hard math down and such but you did a great job :D Love the work <3 Oh and if anyone finds anything cool with these, please post here, I haven't found anything useful with it yet except maybe some cool effect, not really sure, but yeah :D

Re: Hey, so here's a couple functions!

Posted: Wed Dec 14, 2016 1:46 am
by Sir_Silver
Here are some functions I made which you may find some use for.

Code: Select all

function table.clone(tab, tab2)
    local clone = tab2 or {}
   
    for k, v in pairs(tab) do
        if type(v) == "table" then
        	clone[k] = {}
            table.clone(v, clone[k])
        else
        	clone[k] = v 
        end
    end

    return clone
end
This will allow you to take all of the elements from one table and create a new table with all of the same elements. Using recursion, it's able to delve into any of the tables inside of the table you want to copy, and so on, to continue the copying process.

Code: Select all

function PrintTable(tab, indents, printed)
   local spaces = ""
   indents = indents or 0
   printed = printed or {}
   
   for i = 1, indents do
      spaces = spaces .. "        "
   end
   
   printed[tab] = true
   
   for k, v in pairs(tab) do
      if type(v) == "table" and not printed[v] then
         print(spaces .. k .. ":")
         PrintTable(v, indents + 1, printed)
      else
         print(spaces .. k .. ":", v)   
      end
   end
end
If you're familiar with gmod lua, you may already be acquanted with the PrintTable function, this is my take on it, which for what little testing I've done, believe is actually better than the way it works in gmod - because if __index points to the table passed to the function, it won't print everything inside of it again.

Basically it turns this:

Code: Select all

local tab = {
	{
		1,
		2,
		"sky",
		red = {
			true,
			function() end
		},
		"blue"
	},
	"two",
	true
}

tab.__index = tab

PrintTable(tab)
Into this print:

Code: Select all

1:	
        1:	1		
        2:	2		
        3:	sky		
        4:	blue		
        red:	
                1:	true		
                2:	function: 0x1473140		
2:	two		
3:	true		
__index:	table: 0x14725f0	
Pretty neat, huh? :P

EDIT: I changed the table.clone function, so this time it creates a new table instead of using table references.

Re: Hey, so here's a couple functions!

Posted: Wed Dec 14, 2016 2:02 am
by Nicholas Scott
Sir_Silver wrote:Here are some functions I made which you may find some use for.
...
Pretty neat, huh? :P
Yeah it is you show off! Jk, great stuff, I actually started my "programming knowledge" on GLua and was sad when I found out the PrintTable function wasn't native to Lua haha, good stuff bro

Re: Hey, so here's a couple functions!

Posted: Wed Dec 14, 2016 3:50 am
by Sir_Silver
Nicholas Scott wrote:
Sir_Silver wrote:Here are some functions I made which you may find some use for.
...
Pretty neat, huh? :P
Yeah it is you show off! Jk, great stuff, I actually started my "programming knowledge" on GLua and was sad when I found out the PrintTable function wasn't native to Lua haha, good stuff bro
Hey, that's pretty awesome! Didn't figure there were any gmod programmers here. :D Gmod is where I started learning how to program first too!

Re: Hey, so here's a couple functions!

Posted: Wed Dec 14, 2016 6:20 am
by ivan
Not bad, Sir_Silver, it seems like you're headed in the right direction with the code.
I'm not 100% but this looks like a bug:

Code: Select all

        clone[k] = v
        if type(v) == "table" then
            table.clone(v, true)
        end
Without creating a new table "{}", the code would only make a reference so it's not a "deep copy".
Also note that cycles will crash the code above, for example "a = {}; a.b = a".
Note that:

Code: Select all

   for i = 1, indents do
      spaces = spaces .. "        "
   end
Can become:

Code: Select all

spaces = string.rep("   ", indents)
Also, the following part assumes k is a string or a number:

Code: Select all

spaces .. k .. ":"
It's safer to write:

Code: Select all

spaces .. tostring(k) .. ":"
A while ago I wrote a similar table "utilities" file, here it is in a nutshell:

Code: Select all

local _cache = {}

--- Checks if a table is empty
-- @param t Table
-- @return True if empty or false otherwise
function table.empty(t)
  return next(t) == nil
end

--- Removes all values
-- @param t Table
function table.clear(t)
  for i in pairs(t) do
    t[i] = nil
  end
end

--- Counts the number of elements
-- @param t Table
-- @return Number of non-nil values
function table.count(t)
  local n = 0
  for _ in pairs(t) do
    n = n + 1
  end
  return n
end

--- Counts the number of unique elements
-- @param t Table
-- @return Number of unique and non-nil values
function table.ucount(t)
  local n = 0
  local d = 0
  for _, v in pairs(t) do
    if _cache[v] then
      d = d + 1
    end
    n = n + 1
    _cache[v] = true
  end
  -- clear the cache
  table.clear(_cache)
  return n - d, n
end

--- Counts the number of occurrences of a given value
-- @param t Table
-- @param v Value
-- @return Number of occurrences and non-nil values
function table.vcount(t, s)
  assert(s ~= nil, "second argument cannot be nil")
  local n = 0
  local d = 0
  for _, v in pairs(t) do
    if v == s then
      d = d + 1
    end
    n = n + 1
  end
  return d, n
end

--- Reverses the elements in a list
-- @param t Table
-- @param r Destination table (optional)
-- @return Reversed table
function table.reverse(t, r)
  r = r or t
  local n = #t
  if t == r then
    -- reverse in place
    for i = 1, n/2 do
      local i2 = n - i + 1
      r[i], r[i2] = r[i2], r[i]
    end
  else
    -- reverse copy
    for i = 1, n do
      r[n - i + 1] = t[i]
    end
  end
  return r
end

--- Finds the first occurrence in a list
-- @param t Table
-- @param s Search value
-- @param o Starting index (optional)
-- @return Numeric index or nil
function table.find(t, s, o)
  o = o or 1
  assert(s ~= nil, "second argument cannot be nil")
  for i = o, #t do
    if t[i] == s then
      return i
    end
  end
end

--- Finds the last occurrence in a list
-- @param t Table
-- @param s Search value
-- @param o Starting index (optional)
-- @return Numeric index or nil
function table.rfind(t, s, o)
  o = o or #t
  assert(s ~= nil, "second argument cannot be nil")
  -- iterate in reverse
  for i = o, 1, -1 do
    if t[i] == s then
      return i
    end
  end
end

--- Recursive deep copy (internal)
--- "cache" must be empty prior to calling this function
-- @param s Source table
-- @param d Destination table
local function dcopy(s, d)
  -- copy elements from the source table
  for k, v in pairs(s) do
    if type(v) == "table" then
      if _cache[v] then
        -- reference cycle
        d[k] = _cache[v]
      else
        -- recursive copy
        local d2 = d[k]
        if d2 == nil then
          d2 = {}
          d[k] = d2
        end
        _cache[v] = d2
        dcopy(v, d2)
      end
    else
      d[k] = v
    end
  end
end

--- Copies the contents from one table to another
--- Overwrites existing elements in the destination table
--- Preserves table cycles
-- @param s Source table
-- @param d Destination table (optional)
-- @return Resulting table
function table.copy(s, d)
  d = d or {}
  assert(s ~= d, "source and destination tables must be different")
  -- clear the cache
  table.clear(_cache)
  -- deep copy
  dcopy(s, d)
  return d
end

Re: Hey, so here's a couple functions!

Posted: Wed Dec 14, 2016 6:38 am
by Sir_Silver
Thanks for the feedback on that, Ivan, I didn't thoroughly test that function enough, I'll be sure to fix it up when I get the chance! :D