What techniques that everyone should know?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: What techniques that everyone should know?

Post by micha »

Wojak wrote:Inverting an array –
Wouldn't "invert" mean that you actually swap keys and values, instead of setting all values to "true"? That way you could not only check, if an entry exists, but also locate it in the original table.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: What techniques that everyone should know?

Post by kikito »

Check if a table is empty:

Code: Select all

local is_empty = function(t)
  return next(t) == nil
end
Check if a table is an array:

Code: Select all

local function is_array(t)
  local maximum, count = 0, 0
  for k, _ in pairs(t) do
    if type(k) ~= 'number' or k < 1 or math.floor(k) ~= k then return false end
    maximum = math.max(maximum, k)
    count = count + 1
  end
  return count == maximum
end
When I write def I mean function.
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: What techniques that everyone should know?

Post by Ref »

kikito wrote:
Check if a table is an array:

Code: Select all

local function is_array(t)
  local maximum, count = 0, 0
  for k, _ in pairs(t) do
    if type(k) ~= 'number' or k < 1 or math.floor(k) ~= k then return false end
    maximum = math.max(maximum, k)
    count = count + 1
  end
  return count == maximum
end
Note: Doesn't catch arrays in the format - t={ {x=1,y=2},...} as used by the Hardon collider.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: What techniques that everyone should know?

Post by kikito »

Ref wrote:Note: Doesn't catch arrays in the format - t={ {x=1,y=2},...} as used by the Hardon collider.
I don't know what you mean.

Code: Select all

> t = {{x=1,y=2}, {x=2,y=3}}
> print(is_array(t))
true
When I write def I mean function.
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: What techniques that everyone should know?

Post by Roland_Yonaba »

kikito wrote:Check if a table is an array
Yay, I like this. I have something similar in Moses. :)
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: What techniques that everyone should know?

Post by kikito »

Roland_Yonaba wrote:
kikito wrote:Check if a table is an array
Yay, I like this. I have something similar in Moses. :)
Your implementation is very elegant. It's equivalent to this:

Code: Select all

local function isArray(t)
  local count = 0
  for _,_ in pairs(t) do count = count + 1 end
  return count == #t
end
I remember I had some issues with the # operator not returning the correct length in some cases - for example #({1,nil,3}) is 3 instead of 1. I don't remember the details though.

EDIT: I remembered.

Code: Select all

local a = {1,nil,3,a=4}
print(isArray(a)) -- true (depending on the Lua implementation)
When I write def I mean function.
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: What techniques that everyone should know?

Post by Roland_Yonaba »

kikito wrote:

Code: Select all

local a = {1,nil,3,a=4}
print(isArray(a)) -- true (depending on the Lua implementation)
You are so true. The length operator can return falsy answers when given tables containing nil in some cases.
Actually, your version of is_array handles it pretty well. While looping through the given table, in case we find a key which is non numeric (type(k)~='number') or which is lower than 1 (since Lua's array option base is set to 1), or which is not an integer (math.floor(k)~=k), we can safely assume that the given table is not a standard Lua array. This trivially solves the problem, as there is no need to rely on the length operator. Yay.
May I reuse it in Moses ? :nyu:
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: What techniques that everyone should know?

Post by kikito »

Roland_Yonaba wrote:May I reuse it in Moses ? :nyu:
Sure, be my guest.

EDIT:

For the record, I think that if you check the numericality of the keys first, then you can compare count with #t and return that as a result.

Code: Select all

local function is_array(t)
  local count = 0
  for k, _ in pairs(t) do
    if type(k) ~= 'number' or k < 1 or math.floor(k) ~= k then return false end
    count = count + 1
  end
  return count == #t
end
But since the # operator has some weird edge cases, and it could change in the future, I opted for a less implementation-dependant solution.
When I write def I mean function.
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: What techniques that everyone should know?

Post by Ref »

kikito wrote:
Ref wrote:Note: Doesn't catch arrays in the format - t={ {x=1,y=2},...} as used by the Hardon collider.
I don't know what you mean.

Code: Select all

> t = {{x=1,y=2}, {x=2,y=3}}
> print(is_array(t))
true
My bad. My testing invalid.
Thanks for the function.
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: What techniques that everyone should know?

Post by Inny »

kikito wrote:For the record, I think that if you check the numericality of the keys first, then you can compare count with #t and return that as a result.

Code: Select all

local function is_array(t)
  local count = 0
  for k, _ in pairs(t) do
    if type(k) ~= 'number' or k < 1 or math.floor(k) ~= k then return false end
    count = count + 1
  end
  return count == #t
end
But since the # operator has some weird edge cases, and it could change in the future, I opted for a less implementation-dependant solution.
This wouldn't work with embedded nils. Though technically it's not an array anymore when it has an embedded nil, so maybe you're semantically correct.

To demonstrate, this is what Lua does with an embedded nil:

Code: Select all

Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
> =#t
20
> t[5] = nil
> =#t
20
> print(t[5])
nil
But this behavior is undefined, so nobody do it, ok?
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 0 guests