Как я могу проверить, содержит ли таблица lua только последовательные числовые индексы? - PullRequest
7 голосов
/ 20 мая 2011

Как я могу написать функцию, которая определяет, является ли ее аргумент таблицы истинным массивом?

isArray({1, 2, 4, 8, 16}) -> true
isArray({1, "two", 3, 4, 5}) -> true
isArray({1, [3]="two", [2]=3, 4, 5}) -> true
isArray({1, dictionaryKey = "not an array", 3, 4, 5}) -> false

Я не вижу способа узнать, являются ли числовые ключи единственными ключами.

Ответы [ 7 ]

16 голосов
/ 21 мая 2011

EDIT: вот новый способ проверки массивов, который я обнаружил совсем недавно.Для каждого элемента, возвращаемого pairs, он просто проверяет, что n-й элемент на нем не является nil.Насколько я знаю, это самый быстрый и самый элегантный способ проверки массива .

local function isArray(t)
  local i = 0
  for _ in pairs(t) do
    i = i + 1
    if t[i] == nil then return false end
  end
  return true
end
3 голосов
/ 22 мая 2011

ipairs выполняет итерации по индексам 1..n, где n + 1 - это целочисленный индекс first со значением nil.
итерирует по всем ключам.
если ключей больше, чем тамявляются последовательными индексами, то это не может быть массив.

Так что все, что вам нужно сделать, это посмотреть, равно ли количество элементов в pairs(table) числу элементов в ipairs(table)
кодеможно написать следующим образом:

function isArray(tbl)
    local numKeys = 0
    for _, _ in pairs(tbl) do
        numKeys = numKeys+1
    end
    local numIndices = 0
    for _, _ in ipairs(tbl) do
        numIndices = numIndices+1
    end
    return numKeys == numIndices
end

Я довольно новичок в Lua, так что может быть встроена некоторая встроенная функция, которая сводит вычисления numKeys и numIndices к простым вызовам функций.

2 голосов
/ 21 мая 2011

Под "истинным массивом" я предполагаю, что вы имеете в виду таблицу, ключами которой являются только числа.Для этого проверьте тип каждого ключа вашей таблицы.Попробуйте это:

function isArray(array)
    for k, _ in pairs(array) do
        if type(k) ~= "number" then
            return false
        end
    end
    return true --Found nothing but numbers !
end
1 голос
/ 27 октября 2012

Примечание: как указывает @eric, пары не определены для итерации в определенном порядке. Следовательно, это неверный ответ.

Следующего должно быть достаточно; он проверяет, что ключи последовательны от 1 до конца:

local function isArray(array)
  local n = 1
  for k, _ in pairs(array) do
    if k ~= n then return false end
    n = n + 1
  end

  return true
end
0 голосов
/ 23 сентября 2011

Я написал этот код для другого аналогичного вопроса в последнее время:

---Checks if a table is used as an array. That is: the keys start with one and are sequential numbers
-- @param t table
-- @return nil,error string if t is not a table
-- @return true/false if t is an array/isn't an array
-- NOTE: it returns true for an empty table
function isArray(t)
    if type(t)~="table" then return nil,"Argument is not a table! It is: "..type(t) end
    --check if all the table keys are numerical and count their number
    local count=0
    for k,v in pairs(t) do
        if type(k)~="number" then return false else count=count+1 end
    end
    --all keys are numerical. now let's see if they are sequential and start with 1
    for i=1,count do
        --Hint: the VALUE might be "nil", in that case "not t[i]" isn't enough, that's why we check the type
        if not t[i] and type(t[i])~="nil" then return false end
    end
    return true
end
0 голосов
/ 04 июля 2011

Вот мое мнение об этом, используя #array для обнаружения пропуска или остановки, когда слишком много ключей было прочитано:

function isArray(array)
  local count=0
  for k,_ in pairs(array) do
    count=count+1
    if (type(k) ~= "number" or k < 1 or k > #array or count > #array or math.floor(k) ~= k) then 
      return false
    end
  end
  if count ~= #array then
    return false
  end
  return true
end
0 голосов
/ 21 мая 2011

Выполните итерацию от 0 до количества элементов и проверьте, существуют ли все элементы с индексом счетчика. Если это не массив, некоторые индексы будут отсутствовать в последовательности.

...