Table Utils

lua-users home
wiki

Convert a table to a string

Produces a compact, uncluttered representation of a table. Mutual recursion is employed.

function table.val_to_str ( v )

  if "string" == type( v ) then

    v = string.gsub( v, "\n", "\\n" )

    if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then

      return "'" .. v .. "'"

    end

    return '"' .. string.gsub(v,'"', '\\"' ) .. '"'

  else

    return "table" == type( v ) and table.tostring( v ) or

      tostring( v )

  end

end



function table.key_to_str ( k )

  if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then

    return k

  else

    return "[" .. table.val_to_str( k ) .. "]"

  end

end



function table.tostring( tbl )

  local result, done = {}, {}

  for k, v in ipairs( tbl ) do

    table.insert( result, table.val_to_str( v ) )

    done[ k ] = true

  end

  for k, v in pairs( tbl ) do

    if not done[ k ] then

      table.insert( result,

        table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )

    end

  end

  return "{" .. table.concat( result, "," ) .. "}"

end

Example:

t = {['foo']='bar',11,22,33,{'a','b'}}

print( table.tostring( t ) )

This prints {11,22,33,{"a","b"},foo="bar"} .

Recursive table print/stringification/serialization =

See TableSerialization.

Count item occurrences in table

-- Count the number of times a value occurs in a table 

function table_count(tt, item)

  local count

  count = 0

  for ii,xx in pairs(tt) do

    if item == xx then count = count + 1 end

  end

  return count

end

Remove duplicates from table

-- Remove duplicates from a table array (doesn't currently work

-- on key-value tables)

function table_unique(tt)

  local newtable

  newtable = {}

  for ii,xx in ipairs(tt) do

    if(table_count(newtable, xx) == 0) then

      newtable[#newtable+1] = xx

    end

  end

  return newtable

end

Randomly sample from List

RandomSample has a better algorithm but it has the same issue with math.random

-- Careful of random number seeding here- you will need to randomly

-- seed before calling this

function randomlist(l, samp)

  local newlist

  newlist = {}

  if not samp then 

    samp = 0 

  else

    samp = #l - samp

  end

  while #l > samp do

    local idx

    idx = math.random(1, #l)

    newlist[#newlist + 1] = l[idx]

    table.remove(l, idx)

  end

  return newlist

end

Implode table into string with separator

ISSUE: Users should use built-in fn table.concat(table,divider)

-- implode(separator, table)

function implode(d,p)

  local newstr

  newstr = ""

  if(#p == 1) then

    return p[1]

  end

  for ii = 1, (#p-1) do

    newstr = newstr .. p[ii] .. d

  end

  newstr = newstr .. p[#p]

  return newstr

end

Generate combinations from list

-- combo({a,b,c},2) ==> a,b a,c b,c

-- an iterating solution would be appreciated too

function combo(lst, n)

  local a, number, select, newlist

  newlist = {}

  number = #lst

  select = n

  a = {}

  for i=1,select do

    a[#a+1] = i

  end

  newthing = {}

  while(1) do

    local newrow = {}

    for i = 1,select do

      newrow[#newrow + 1] = lst[a[i]]

    end

    newlist[#newlist + 1] = newrow

    i=select

    while(a[i] == (number - select + i)) do

      i = i - 1

    end

    if(i < 1) then break end

    a[i] = a[i] + 1

    for j=i, select do

      a[j] = a[i] + j - i

    end

  end

  return newlist

end

Generate combinations from list - Iterator version

Should be faster for large t and n as it updates only the items that change from combo to combo, instead of recreating the combo row each iteration.

By RichardWarburton.

function combo(t,n)

  local n,max,tn,output=n,#t,{},{}

  for x=1,n do tn[x],output[x]=x,t[x] end -- Generate 1st combo

  tn[n]=tn[n]-1 -- Needed to output 1st combo

  return function() -- Iterator fn

    local t,tn,output,x,n,max=t,tn,output,n,n,max

    while tn[x]==max+x-n do x=x-1 end -- Locate update point

    if x==0 then return nil end -- Return if no update point

    tn[x]=tn[x]+1 -- Add 1 to update point (UP)

    output[x]=t[tn[x]] -- Update output at UP

    for i=x+1,n do 

      tn[i]=tn[i-1]+1 -- Update points to right of UP

      output[i]=t[tn[i]] -- Update output to refect change in points

    end

    return output

  end

end

Insert values from one table into another table

--DavidManura

-- tinsertvalues(t, [pos,] values)

-- similar to table.insert but inserts values from given table "values",

-- not the object itself, into table "t" at position "pos".

-- note: an optional extension is to allow selection of a slice of values:

--   tinsertvalues(t, [pos, [vpos1, [vpos2, ]]] values)

-- DavidManura, public domain, http://lua-users.org/wiki/TableUtils

function tinsertvalues(t, ...)

  local pos, values

  if select('#', ...) == 1 then

    pos,values = #t+1, ...

  else

    pos,values = ...

  end

  if #values > 0 then

    for i=#t,pos,-1 do

      t[i+#values] = t[i]

    end

    local offset = 1 - pos

    for i=pos,pos+#values-1 do

      t[i] = values[i + offset]

    end

  end

end

--[[ tests:

  local t = {5,6,7}

  tinsertvalues(t, {8,9})

  tinsertvalues(t, {})

  tinsertvalues(t, 1, {1,4})

  tinsertvalues(t, 2, {2,3})

  assert(table.concat(t, '') == '123456789')

--]]

Iterate over the non-ipairs keys in a table

See LuaList:2010-12/msg01143.html ("hpairs" discussion).

See Also

Comments

Maybe rename this to TableRecipes? (like StringRecipes).


RecentChanges · preferences
edit · history
Last edited January 2, 2011 1:31 pm GMT (diff)