table iteration problem

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

table iteration problem

Victor Young
For example, I have following codes:

t = {
x=1,
y=2,
a=3,
b=4
}

for k, v in pairs(t) do
print(k, v)
end

then the output is:
y       2
x       1
a       3
b       4

If I want the output to be like follow:
x       1
y       2
a       3
b       4
just in the order of how I construct the table, how could I do? Thanks!
Reply | Threaded
Open this post in threaded view
|

Re: table iteration problem

steve donovan
On Tue, Oct 18, 2011 at 5:56 AM, Victor Young <[hidden email]> wrote:
> just in the order of how I construct the table, how could I do? Thanks!

Short answer: such tables do not have a stable iteration order (it's
the usual semi-random hash table thing)

To get the order you want, one way is to keep a sub-table of the keys
in order, and use that for iteration.

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: table iteration problem

Dirk Laurie-2
In reply to this post by Victor Young
2011/10/18 Victor Young <[hidden email]>:
> For example, I have following codes:
> t = {
> x=1,
> y=2,
> a=3,
> b=4
> }

> If I want the output to be like follow:
> x       1
> y       2
> a       3
> b       4
> just in the order of how I construct the table, how could I do? Thanks!

After that `t={…}` the order of construction is gone.  No way to get
it back. There are several ways to do what you want, but all of them
rely on keeping the list {'x','y','a','b'} somewhere.

Dirk

Reply | Threaded
Open this post in threaded view
|

Re: table iteration problem

Victor Young
In reply to this post by steve donovan
I've considered this method before. It's useful, but when the table has many keys, it will be troublesome and easy to make mistakes. Thanks any way!

2011/10/18 steve donovan <[hidden email]>
On Tue, Oct 18, 2011 at 5:56 AM, Victor Young <[hidden email]> wrote:
> just in the order of how I construct the table, how could I do? Thanks!

Short answer: such tables do not have a stable iteration order (it's
the usual semi-random hash table thing)

To get the order you want, one way is to keep a sub-table of the keys
in order, and use that for iteration.

steve d.


Reply | Threaded
Open this post in threaded view
|

Re: table iteration problem

Mark Hamburg
On Oct 17, 2011, at 11:27 PM, Victor Young wrote:

I've considered this method before. It's useful, but when the table has many keys, it will be troublesome and easy to make mistakes. Thanks any way!

You could construct things as:

local t = magic_table()
-- t records the sequence in which keys are first assigned

t.x = 1
t.y = 2
t.a = 3
t.b = 4

for k, v in t:iter() do
print( k, v )
end

The __pairs metamethod in 5.2 (I think) will avoid the problem with stealing the key iter in the above example.

Mark

Reply | Threaded
Open this post in threaded view
|

Re: table iteration problem

steve donovan
In reply to this post by Victor Young
On Tue, Oct 18, 2011 at 8:27 AM, Victor Young <[hidden email]> wrote:
> I've considered this method before. It's useful, but when the table has many
> keys, it will be troublesome and easy to make mistakes. Thanks any way!

That's true, so let's see if there's a better notation

t = ordered {
  {a = 1},
  {b = 2},
  {c = 3}
}

function ordered (spec)
   local t = { _keys = {} }  -- our output table, containing keys array
   for i,pair in ipairs(spec) do
      local k,v = next(pair)
      t[k] = v
      t._keys[i] = k
   end
   return t
end

that is, you end up with {a=1,b=2,c=3,_keys={'a','b','c'}}

Note the trick with the next() function - gets the first key-value pair!

Now you can do

for _,key in ipairs(t._keys) do
   local value = t[key]
   ...
end

steve d.

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: table iteration problem

Enrico Colombini
In reply to this post by steve donovan
On 18/10/2011 8.09, steve donovan wrote:
> To get the order you want, one way is to keep a sub-table of the keys
> in order, and use that for iteration.

Or, assuming numbers here are arbitrary and not just consecutive, if you
need a table of pairs you could store them as subtables:

-- elements with no key are stored in order (table as array)
t = {
   {'x', 1},
   {'y', 2},
   {'a', 3},
   {'b', 4}
}

-- read them back in the same order (note 'ipairs')
for _, s in ipairs(t) do
   print(s[1], s[2])
end

--> output:
x       1
y       2
a       3
b       4

--
   Enrico

Reply | Threaded
Open this post in threaded view
|

Re: table iteration problem

Victor Young
In reply to this post by steve donovan
It seems to be a simple and flexible method, thank you and Enrico

2011/10/18 steve donovan <[hidden email]>
On Tue, Oct 18, 2011 at 8:27 AM, Victor Young <[hidden email]> wrote:
> I've considered this method before. It's useful, but when the table has many
> keys, it will be troublesome and easy to make mistakes. Thanks any way!

That's true, so let's see if there's a better notation

t = ordered {
 {a = 1},
 {b = 2},
 {c = 3}
}

function ordered (spec)
  local t = { _keys = {} }  -- our output table, containing keys array
  for i,pair in ipairs(spec) do
     local k,v = next(pair)
     t[k] = v
     t._keys[i] = k
  end
  return t
end

that is, you end up with {a=1,b=2,c=3,_keys={'a','b','c'}}

Note the trick with the next() function - gets the first key-value pair!

Now you can do

for _,key in ipairs(t._keys) do
  local value = t[key]
  ...
end

steve d.

steve d.


Reply | Threaded
Open this post in threaded view
|

Re: table iteration problem

Dirk Laurie-2
2011/10/18 Victor Young <[hidden email]>:
> It seems to be a simple and flexible method, thank you and Enrico

I append another solution to this solved problem :-)

Dirk

history.lua (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: table iteration problem

Victor Young
It's another useful method, thanks!

2011/10/18 Dirk Laurie <[hidden email]>
2011/10/18 Victor Young <[hidden email]>:
> It seems to be a simple and flexible method, thank you and Enrico

I append another solution to this solved problem :-)

Dirk