Вложенные таблицы и числовые клавиши в Lua

Я не уверен, возможно ли это из-за числовых индексов, но, надеюсь, кто-то может указать мне правильное направление.

Учитывая таблицу:

t = { 13, 200, 12, 15, 23 }

как я могу вложить таблицу, используя числа?

t["200"] = {"stuff", "more stuff", "even more stuff"}

не работает, так как создаст позицию 200 и заполнит пустые ячейки нулевым значением. Я бы добавил букву в качестве суффикса/префикса, но возникает проблема с численной сортировкой таблицы. Это вообще возможно, или я застрял с другим методом? Спасибо!

Небольшое редактирование из-за реализации:

t["200"] = {"stuff", "more stuff", "even more stuff"}

фактически создает ключ «200», тогда как:

t[200] = {"stuff", "more stuff", "even more stuff"}

создает индекс 200 со всем остальным нулевым.


person Josh    schedule 18.06.2011    source источник


Ответы (3)


Во-первых, DeadMG прав; вы использовали строку, а не числовой индекс. Однако даже если бы вы использовали числовой индекс, это не помогло бы.

Если вы сделаете это:

someTable = {"value1", "value2", {"value3a", "value3b"}};
someTable[50] = {"value50a", "value50b"};

Длина таблицы #someTable по-прежнему будет 3. Почему? Потому что Lua определяет массивы в таблице на основе смежных элементов. Помните: вы можете получить доступ к любому элементу любой таблицы; все они концептуально заполнены nil, пока вы не присвоите им фактическое значение.

Lua определяет длину таблицы как количество значений в таблице, если вы начинаете отсчет с числового индекса 1, пока не достигнете первого значения nil. Поскольку someTable[4] равно нулю, длина равна 3.

Если вы хотите вставить новый элемент в конец таблицы массива, вы можете сделать это:

someTable[#someTable + 1] = "newValue";

Само значение может быть таблицей:

someTable[#someTable + 1] = {"newValuea", "newValueb"};

Если вы просто спрашиваете, как получить доступ к вложенной таблице, это просто и не имеет ничего общего с используемыми вами ключами.

Во вложенных таблицах нет ничего особенного. Таблицы — это значения, а записи в таблицах могут быть любыми значениями, включая другие таблицы.

Если у вас есть таблица и вы хотите просмотреть записи массива в ней, вы используете это:

local aTable = {"first", "second", "third", ...}
for i, value in ipairs(aTable) do
    --`value` contains the entries in the table.
end

Вложенная таблица ничем не отличается; это просто вопрос получения таблицы. локальная вложенная таблица = { "первая", "вторая", "третья", ...} вложенная таблица [# вложенная таблица + 1] = {"новая первая", "новая вторая", ...} локальная таблица = вложенная таблица [# вложенная таблица]; для i значение в ipairs(aTable) do --value содержит записи в таблице. конец

Или вы могли бы просто сделать ipairs(nestedTable[#nestedTable]). Обратите внимание, что используемый здесь конкретный ключ (целочисленное значение) совершенно не важен. Этот ключ мог быть строкой, числом с плавающей запятой, другой таблицей, некоторыми пользовательскими данными и т. д. Это не имеет значения.

Также обратите внимание, что мы используем ipairs, потому что мы хотим перебирать только элементы массива таблицы. Длина массива определена выше. Если бы мы хотели перебрать каждого члена таблицы, мы бы использовали pairs вместо ipairs. Конечно, pairs выполняет неупорядоченный поиск, поэтому не гарантируется, что он будет в порядке массива.

Если вы хотите рекурсивно найти каждый элемент во вложенной таблице, вы можете сделать это:

local function RecursiveSearch(aTable)
    for key, value in pairs(aTable) do --unordered search
        if(type(value) == "table") do
            RecursiveSearch(value)
        else
            --Do something with this.
        end
    end
end

Обратите внимание, что приведенное выше может выполнять бесконечный цикл, поскольку таблица может иметь циклические ссылки:

local tableA = {}
local tableB = {tableA}
local tableA[1] = tableB
RecursiveSearch(tableA) --Infinite loop.
person Nicol Bolas    schedule 18.06.2011
comment
Однако я не хочу добавлять новый элемент. Я хочу отредактировать существующий элемент (скажем, 200 в данном случае), сделав его вложенной таблицей. В идеале я хотел бы получить эту таблицу с помощью t[200] и в будущем выполнить foreach для внутренней таблицы. - person Josh; 19.06.2011
comment
@Josh: Ваш первоначальный вопрос был сосредоточен на том, как добавление элемента 200 в таблицу привело к тому, что записи между концом списка и элементом 200 были заполнены нулями. Я добавил в свой ответ раздел, посвященный обходу вложенных таблиц. - person Nicol Bolas; 19.06.2011

Возможно, это поможет просмотреть ваше задание следующим образом:

t = { [1] = 13, [2] = 200, [3] = 12, [4] = 15, [5] = 23 }

Чтобы изменить то, что в настоящее время 200 (а именно t[2]), вы делаете:

t[2] = {"stuff", "more stuff", "even more stuff"}

Изменить: в результате ваша таблица будет выглядеть так:

t = { [1] = 13, [2] = {"stuff", "more stuff", "even more stuff"}, [3] = 12, [4] = 15, [5] = 23 }
-- or, equivalent::
t = { 13, {"stuff", "more stuff", "even more stuff"}, 12, 15, 23 }
person Jasmijn    schedule 18.06.2011

Проблема в том, что вы используете "". Ваша таблица t содержит набор чисел, и вы вводите строку в качестве ключа. Вы хотите перебрать таблицу и сделать... что-то, что вы не очень хорошо определили. Однако вы не можете добавлять данные в таблицу во время ее повторения, поэтому вам, возможно, придется делать некоторые забавные вещи.

t = { 13, 200, 12, 15, 23 }
newt = {};
for key, value in pairs(t) {
    newt[value] = { }; 
}

Это создаст запись таблицы в newt, где ключ является значением в таблице t для всех значений в t.

person Puppy    schedule 18.06.2011
comment
Хорошо, после этого как бы я назвал значения? Причина, по которой цифры случайны, заключается в том, что они представляют разные уровни снаряжения в MUD, в который я играю. Поэтому я храню различное оборудование в каждом ключе уровня. Если я захочу забрать оборудование этого уровня, как мне позвонить? newt[уровень] или t[newt[уровень]]? Или что-то другое? - person Josh; 19.06.2011