If i try to output this table, they are looped through in the false order:
local letters = {DIN1="hi", AIN1= "my", AIN2 ="name", DIN2="is"}
for name, value in pairs(letters) do
print(name,value)
end
Expected Output:
DIN1 hi
AIN1 my
AIN2 name
DIN2 is
Output:
AIN1 my
DIN2 is
DIN1 hi
AIN2 name
How can i code it so that the for loop runs through the tables actual order? (The order how it was defined)
Edit: I don't need the alphabetic order, but the same order as in the definition of the table.
Edit: I need to have the key AND the value printed. In the answer "Lua in pairs with same order as it's written" there will be only indexnumber and value printed
You may utilize integer part of the table to store keys in order:
function add(t, k, v, ...)
if k ~= nil then
t[k] = v
t[#t+1] = k
return add(t, ...)
end
return t
end
t = add({ }, "A", "hi", "B", "my", "C", "name", "D", "is")
for i,k in ipairs(t) do
local v = t[k]
print(k, v)
end
Of course, this assumes that integer keys are not used by anything except add
.
insert(t, k, v)
and remove(t, k)
left as an exercise to the reader.
EDIT:
Ellipsis (dots) in add
function allow passing as many arguments as needed to set many kv-pairs at once. Without that, we would be only able to set one pair per call, like add(t, "A", "hi")
. Function definition add(t, k, v, ...)
assigns first three arguments to t, k, v
and leaves others untouched. Then add
processes first pair (t[k]=v
) and recurses with the rest ...
of arguments.
t k v ...
level 1: (t, "A", "hi", "B", "my", "C", "name", "D", "is")
level 2: (t, <- "B", "my", "C", "name", "D", "is")
level 3: (t, <- "C", "name", "D", "is")
level 4: (t, <- "D", "is")
level 5: (t, <- )
At level 5, k
and v
take nil
s, because argument list is too short, and recursion stops.
The Lua-users wiki has a page that addresses this particular problem.
Quoting the code from that page:
--[[
Ordered table iterator, allow to iterate on the natural order of the keys of a
table.
Example:
]]
function __genOrderedIndex( t )
local orderedIndex = {}
for key in pairs(t) do
table.insert( orderedIndex, key )
end
table.sort( orderedIndex )
return orderedIndex
end
function orderedNext(t, state)
-- Equivalent of the next function, but returns the keys in the alphabetic
-- order. We use a temporary ordered key table that is stored in the
-- table being iterated.
key = nil
--print("orderedNext: state = "..tostring(state) )
if state == nil then
-- the first time, generate the index
t.__orderedIndex = __genOrderedIndex( t )
key = t.__orderedIndex[1]
else
-- fetch the next value
for i = 1,table.getn(t.__orderedIndex) do
if t.__orderedIndex[i] == state then
key = t.__orderedIndex[i+1]
end
end
end
if key then
return key, t[key]
end
-- no more value to return, cleanup
t.__orderedIndex = nil
return
end
function orderedPairs(t)
-- Equivalent of the pairs() function on tables. Allows to iterate
-- in order
return orderedNext, t, nil
end
Not that natural order of the keys here means that you start with the smallest key (as if determined by a < b
style comparisons), which is not necessarily the key that you write first in your code when filling the table (determining the latter is way more complicated and way less reasonable).
You can then simply use the orderedPairs
function as a drop-in replacement for pairs
:
local letters = {A="hi", B= "my", C ="name", D="is"}
for name, value in orderedPairs(letters) do
print(name,value)
end
For the record, there is no exact order.
A table in Lua is a set of key-value pairs. A table definition is just shorthand for setting several pairs at once. The order the pairs are defined only matters when there are repeated keys: the last pair with the same key is the one that remains in the table.
I was able to work around it with this code, but this solution is not perfect of course.
local letters = {"DIN1=hi", "DIN2 = my", "AIN1 = name", "LE = is" }
local pattern = "(%S+)%s*=%s*(%S+)"
for _, n in pairs(letters) do
key, value = n:match(pattern)
print(key, value)
end
Output:
DIN1 hi
DIN2 my
AIN1 name
LE is