1

What is the most efficient way to convert number to table? Or is it possible to make a table without loops?

local t = 10 -- given number
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} -- result

Update: the t variable is mutable number and I want to for each the value.

t = 3

function foreach(f, t)
  for i, v in ipairs(t) do
    f(v)
  end   
end

foreach(print, t)
1
2
3

I need a just the quickest way of new Array(n) in Lua. Or doesn't make any sense?

jackson555
  • 31
  • 1
  • 4
  • 2
    Could you share with us, why you would want such a table? If your only goal is to have a table whichs length is 10 but which don't necceseraly have 10 elements then `table.setn` can be used. – Sebastian Hoffmann Feb 28 '16 at 10:25
  • you can export `lua_createtatble` to Lua. table.setn is depricated and just set `n=x` but does not allocate memory (I am not sure about this). But I really suggest make perfomance test before implement any implementation. – moteus Feb 28 '16 at 11:05
  • @SebastianHoffmann Thanks for your comment. I want to avoid the double loop in this example. But I got `foo = {}; print(table.setn(foo, 10))` stdin:1: attempt to call field 'setn' (a nil value) stack traceback: stdin:1: in main chunk [C]: in ? ` – jackson555 Feb 28 '16 at 11:14
  • @moteus Thanks for your comment. it sounds tough to me. I'm trying to find the `lua_createtable` way. – jackson555 Feb 28 '16 at 11:23
  • Just create an empty table `arr = {}`. Lua tables are able to grow indefinitely on-the-fly. No explicit memory allocation is required. – Egor Skriptunoff Feb 28 '16 at 12:24
  • @EgorSkriptunoff Thanks for your comment. I just iterate for-loop from a given number. Shall I use while-loop instead for-loop in Lua? – jackson555 Feb 28 '16 at 12:51
  • @EgorSkriptunoff Wouldn't it be enough just to set the value of the highest index? Following the [table source](https://github.com/lua/lua/blob/master/src/ltable.c), creating a new key for the array part should allocate enough memory and fill other fields with _nil_. – Youka Feb 28 '16 at 15:18
  • @jackson555 Are you concerned with a particular Lua implementation's performance or just how to use the Lua language and standard libraries? (If performance, which implementation and version?) – Tom Blodget Feb 28 '16 at 15:23
  • @Youka It seems, not. Reading just the header comment from the implementation you referenced, "The actual size of the array is the largest 'n' such that more than half the slots between 1 and n are in use." – Tom Blodget Feb 28 '16 at 15:29
  • @Youka: No. The size of the array part of a table in Lua is the first non-`nil` element, when counting from 1. If you just set `[20] = value`, the first non-`nil` element will still be `[1]`. – Nicol Bolas Feb 28 '16 at 17:47
  • @NicolBolas That is the size of the "sequence" that a table might have. [Sequence](http://www.lua.org/manual/5.3/manual.html#3.4.7) is a Lua language/library concept relevant to the definition of `#` and `ipairs`. @Youka is talking about one implementation's internal data structure that stores some table element values in one block of directly indexable, key-ordered memory ("array part"). [Yes, the technique can be and is used across many versions and implementations.] – Tom Blodget Feb 28 '16 at 19:04
  • 1
    @TomBlodget: Yes, but you cannot access the implementation's "internal data structure" from *Lua script*. And the OP was asking about what you can do from Lua. – Nicol Bolas Feb 28 '16 at 19:18
  • Will you be changing the elements of the table, or will they always be 1 through n? – warspyking Feb 29 '16 at 10:38

2 Answers2

2

Maybe you don't know how to answer @Sebastian's question. Here are a few alternatives to get you thinking.

Since your table has only computed elements, you could omit the storage and just perform the calculation on every read access (index operation).

local function newArray(size)
    local t = {}
    setmetatable(t, {
           __index = function (_, i) 
               return i >= 1 and i <= size and i or nil end})
    return t
end

t10 = newArray(10)
for i = 0, 11 do -- ipairs won't work as expected with such a table
    print(i, t10[i])
end
t10[2] = "stored values override __index"
print(t10[2])

Of course, you could also replace the table with just an identity function that returns the value, or even just an identity expression. But, maybe you have an unexpressed requirement for a table or you need ipairs to iterate over the sequence.

Speaking of iterators,

local function seq_itor(first, last)
    local i = first - 1
    return function ()
        i = i + 1
        if i <= last then return i end
    end
end

for i in seq_itor(1, 10) do
    print(i)
end
Tom Blodget
  • 20,260
  • 3
  • 39
  • 72
1

The simplest way to do that would be to define a function:

function newArray(size)
    local t = {}
    for i = 1, size do
        t[i] = i
    end
    return t
end
Jasmijn
  • 9,370
  • 2
  • 29
  • 43