Page 4 of 8

Re: What techniques that everyone should know?

Posted: Tue Feb 25, 2014 11:56 am
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.

Re: What techniques that everyone should know?

Posted: Tue Feb 25, 2014 12:24 pm
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

Re: What techniques that everyone should know?

Posted: Tue Feb 25, 2014 4:06 pm
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.

Re: What techniques that everyone should know?

Posted: Tue Feb 25, 2014 4:27 pm
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

Re: What techniques that everyone should know?

Posted: Tue Feb 25, 2014 4:31 pm
by Roland_Yonaba
kikito wrote:Check if a table is an array
Yay, I like this. I have something similar in Moses. :)

Re: What techniques that everyone should know?

Posted: Tue Feb 25, 2014 5:00 pm
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)

Re: What techniques that everyone should know?

Posted: Tue Feb 25, 2014 9:28 pm
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:

Re: What techniques that everyone should know?

Posted: Tue Feb 25, 2014 9:57 pm
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.

Re: What techniques that everyone should know?

Posted: Tue Feb 25, 2014 11:31 pm
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.

Re: What techniques that everyone should know?

Posted: Wed Feb 26, 2014 1:53 am
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?