ColR_iT 171 Опубликовано 9 Сентября 2012 Накопилось много вопросов по Lua в целом, буду задавать по порядку... Как выделяется память для таблиц? Подозреваю, что на каждый элемент таблицы, плюс если это хеш-таблица, то ещё и на ключи. Так ли это? Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 9 Сентября 2012 Боюсь, что последующие вопросы не особо связаны какой-либо идеей, разве что они относятся к Lua. А вопрос вроде бы достаточно адекватен: как выделяется память под таблицы? Например для строки - это равно количество символов в строке плюс один байт. Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 11 Сентября 2012 (изменено) В целом разобрался, спасибо. Ещё вопрос: есть ли принципиальная разница между использованием tbl[index] и tbl.index, возможно в скорости работы или ещё какие-нибудь нюансы? Изменено 11 Сентября 2012 пользователем ColR_iT Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 16 Сентября 2012 (изменено) AndreySol, это значит, что таблица new_table будет иметь следующий вид: new_table = { [key1_name] = { ["param1"] = {} } } Изменено 16 Сентября 2012 пользователем ColR_iT 1 Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 17 Сентября 2012 (изменено) AndreySol, скажем так - это некоторая особенность языка. Если совсем поверхностно и ты знаком хотя бы с основами ООП, то обращение к элементам таблицы через квадратные скобки - это обращение как к элементам таблицы, а через точку - как к структуре. Если глубже - тогда тебе читать документацию по Lua. P.S. Вот такие две записи эквивалентны: tbl = {} tbl["index1"] = 1 tbl.index1 = 1 Обе эти записи обозначают, что в таблицу tbl записан новый элемент равный числу 1, под индексом "index1". Есть и другие особенности применения точки для таблиц. Например в игре, все функции что ты используешь - это по сути одна большая таблица, если быть точным, то это таблица _G. И когда ты в какой-нибудь функции пишешь что-то вроде такого: file_name.function_name() Это означает, что нужно из таблицы file_name найти элемент function_name, а поскольку это функция, то ты вызываешь функцию. P.P.S. Буду рад любой критике. Изменено 17 Сентября 2012 пользователем ColR_iT 2 Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 17 Сентября 2012 Viнt@rь, возможно я не до конца понял твою мысль, но точно можно сделать так: tbl = {} for i=1, 3 do tbl["vName_"..i] = "vName_"..i end Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 18 Сентября 2012 (изменено) Shredder, конкретного оператора нет, но это можно с имитировать. for i=1, 3 do if i ~= 2 then print (i) end end Результат понятен - пропускается цикл со значением счётчика равному двум. Конечно, это далеко не универсальный вариант, но он работает. Изменено 18 Сентября 2012 пользователем ColR_iT Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 18 Сентября 2012 (изменено) Shredder Дык, а table.foreach ничем не отличается от того же итератора pairs. Для foreach передается два параметра: первый таблица, второй - функция, в функцию же автоматом передаётся два значения: ключ и значение этого ключа. И так происходит для всей таблицы, т.е. в функцию передаётся поочерёдно все ключи указанной таблицы. Абсолютно тоже самое происходит и с конструкцией вида: for key, value pairs(table) do -- здесь по сути тело функции, которая передавалась вторым параметром для foreach. end Всё также пробегаемся по всем ключам таблицы и если ничего не вернули (отсутствует оператор break), то перебирать будем всю таблицу. P.S. А к стати table.foreach в игре осталась? Вроде как её и table.foreachi нет с какой-то версии lua. Сейчас глянул в 5.0 ещё были, в 5.1 уже исключили из стандартного набора. В игре какая версия используется? Ещё заглянул в _G в 1.0006. Там функция foreach ещё есть. Но в любом случае - не вижу смысла её использовать... Изменено 18 Сентября 2012 пользователем ColR_iT Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 19 Сентября 2012 (изменено) Ложка дёгтя в бочку мёда... Попытался вычислить время работы обоих итераторов в игре (ТЧ 1.0006 + X-Ray extension), вот результаты работы: tbl = { ["a"] = 1, ["b"] = 2, ["c"] = 3, ["d"] = 4, ["e"] = 5, } tbl2 = {} tbl3 = {} local timer = profile_timer() timer:start() for i = 1, 1000000 do for k,v in pairs(tbl) do if k~="b" then tbl2.k = v end end end timer:stop() log1("##Time is "..timer:time()) --# 0.6806496875 sec timer:start() for i = 1, 1000000 do table.foreach (tbl, function (k,v) if k == "b" then return end tbl3.k = v end) end timer:stop() log1("##Time is "..timer:time()) --# 1.581734375 sec Как видно pairs выигрывает более чем в два раза. P.S. Поправил результаты. profile_timer считает время в микросекундах, а я делил результат на 105. Изменено 19 Сентября 2012 пользователем ColR_iT Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 19 Сентября 2012 Эх, будет мне наукою... Как оказалось метод start() класса profile_timer не обнуляет значение, а продолжает считать. Вот ПРАВИЛЬНЫЕ результаты эксперимента: --#------------------------------------------------------------ tbl = { ["a"] = 1, ["b"] = 2, ["c"] = 3, ["d"] = 4, ["e"] = 5, } tbl2 = {} tbl3 = {} tbl4 = {} --#------------------------------------------------------------ local timer1 = profile_timer() timer1:start() for i = 1, 1000000 do for k,v in pairs(tbl) do if k~="b" then tbl2.k = v end end end timer1:stop() log1("##Time is "..timer1:time()) --# 0.684159375 sec --#------------------------------------------------------------ local timer2 = profile_timer() timer2:start() for i = 1, 1000000 do table.foreach (tbl, function (k,v) if k == "b" then return end tbl3.k = v end) end timer2:stop() log1("##Time is "..timer2:time()) --# 0.9012660625 sec --#------------------------------------------------------------ local function f(k,v) if k == "b" then return end tbl4.k = v end local timer3 = profile_timer() timer3:start() for i = 1, 1000000 do table.foreach (tbl, f) end timer3:stop() log1("##Time is "..timer3:time()) --# 0.7032258125 sec --#------------------------------------------------------------ И как видно, в эксперименте появился третий вариант (спасибо Charsi). Результаты на лицо. Так что Shredder - приношу свои извинения за дезинформацию. Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 24 Сентября 2012 (изменено) Dennis_Chikin, извиняюсь, что не совсем в тему, но по первому вопросу есть и другой способ вернуть из строки - числа. str = " -195.01,-5.12, 146.45, 50" a, b, c, d = loadstring("return "..str)() print (a, b, c, d) --# Результат числа: -195.01 -5.12 145.45 50 Работать будет для строки, которая состоит из чисел разделённые запятыми. Изменено 24 Сентября 2012 пользователем ColR_iT Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 30 Октября 2012 (изменено) proger_Dencheek, в самом алгоритме есть логическая ошибка. При первых пяти вызовах, будет действительно выдаваться рандомные сообщения и они будут удаляться из массива aa, а массив bb будет заполнятся, до тех пор, пока все элементы aa не перекочуют в bb. Шестой вызов будет использовать массив bb, поскольку проверка if next(aa) then вернёт false. А вот уже седьмой вызов будет вновь использовать массив aa, потому как на предыдущем этапе в него был помещён одни элемент из массива bb, и вышеупомянутая проверка благополучно вернёт истину. Далее действо будет ходить по кругу: восьмой вызов - массив bb, девятый - aa и т.д. Поэтому используй алгоритм предложенный Gun12, он лишён данного недостатка. Про "бардак" совершенно не ясно, что ты имеешь ввиду... P.S. И давай более внятные имена переменным, даже на этапе тестирования, это поможет избежать путаницы. Изменено 30 Октября 2012 пользователем ColR_iT Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 30 Октября 2012 (изменено) proger_Dencheek, ты только всё усложнил. В целом ход твоих мыслей, лично я понял, но ты не учёл один момент. Вот это: local arhiv = tbl не создаёт копию таблицы, а присваивает ссылку на таблицу, т.е. arhiv и tbl это одна и та же таблица. Так что не изобретай велосипед и используй алгоритм Gun12, он на 101% рабочий. Изменено 30 Октября 2012 пользователем ColR_iT Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 30 Октября 2012 proger_Dencheek, как раз таки наоборот. Алгоритм Gun12, не повторяет сообщения, а алгоритм от Artos может на третий раз выдать сообщение которое уже было первым. Это очень легко просматривается в обоих случаях. На счёт копии - да, так будет копия. Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 27 Марта 2013 Callisto, в любом маломальском пособии по Lua, есть исчерпывающая информация по табличным функциям. table.remove (table, pos)Первый аргумент (обязательный) - это таблица из которой происходит удаление. Второй (необязательный) - это позиция с которой нужно удалить элемент таблицы. Если параметр не указывать, то удалит последний элемент таблицы. При удалении, индексы элементов выше, сдвигаются вниз. Работает только с индексированными таблицами. В твоём же случае нужно присваивать ключу, значение которое ты хочешь удалить, значение nil. Например: table_1.0201 = nilНа Wiki есть неплохая статья по таблицам за авторством iDreD: >>ClicK Me<<, есть что почитать... 1 Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 26 Мая 2013 toxictrace, а ты уверен, что в качестве key ты передаёшь то, что нужно? Это единственная причина подобной ошибки. Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 27 Мая 2013 Real Wolf, в Lua по другому то и не выйдет. К сожалению, я не знаю механизма реализации наследования в LuaBind, но мне кажется, что от обычного Lua'шного способа с копированием таблиц и метатаблиц он не сильно отличается. LuaBind это ведь "обёртка", упрощающая написание кода или я ошибаюсь? Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 11 Июня 2013 (изменено) У меня есть шесть абсолютно одинаковых функций, разные лишь названия, я их заношу в табличку и когда названия разные - никаких проблем нет. В целях уменьшения размера кода, я хочу сделать одну "общую" функцию и для шести функций передать ссылку на неё, но при занесении их в таблицу сталкиваюсь с тем, что первая функция затирается второй и т.д. Вот пример: function func (value) print (value) end tbl = {} function Past(f,v) tbl[f]={v=v} end function OnPrint() func2 = func func3 = func Past (func2, "two") Past (func3, "three") for fun,val in pairs (tbl) do fun(val.v) end endПри вызове функции OnPrint, естественно, в качестве результата я вижу лишь "three", т.к. func2 и func3 это ссылки на func.Вопрос: можно ли подправить код так, чтобы в результатах отобразилась и "two" и "three" без явного вызова функции func в функциях func2 и func3? Изменено 11 Июня 2013 пользователем ColR_iT Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 11 Июня 2013 @abramcumner, не очень понял о чём Вы. @Shredder, при таком подходе не получится удалить один элемент из таблицы таким образом: tbl[f] = nilТ.к. удаляться они будут по отдельности, а так выйдет все скопом. 1 Поделиться этим сообщением Ссылка на сообщение
ColR_iT 171 Опубликовано 11 Июня 2013 (изменено) Тупанул, когда не объяснил всей сути, признаю... Если кто знаком с файлом xr_s.script, то тому код будет знаком. У меня есть в целом вот такая конструкция: tbl = {} function Register(f,v) tbl[f]={v=v} end function Unregister (f) tbl[f]=nil end --#--------- function update () for func,param in pairs(tbl) do func(param.v) end end --#--------- function func2 (value) print (value) end function func3 (value) print (value) end function Past() Register (func2, "two") Register (func3, "three") endФункции func2 и func3 вносятся в таблицу tbl посредством функции Register, это я делаю в нужный мне момент. Функция update периодически обновляется и тем самым апдейтит обе мои функции func2 и func3. Когда мне не нужно обновлять, например, функцию func2, я вызываю функцию Unregister(func2) и тем самым оставляю в биндящейся функции, а точнее в таблице, итерация которой находится там, лишь func3.Со временем функции func2 и func3 разрослись (к тому же их не две, а шесть) и стали изрядно занимать место. Т.к. функции имеют одинаковое тело, то я подумал, почему бы не сократить код до одной "общей" функции, а передавать ссылку на неё шести другим (к сожалению, передачи по значению в Lua нет), но столкнулся с проблемой, которую не смог обойти, скажем так, изящнее, нежели вызывать одну общую функцию внутри этих шести, на манер такого: function func (value) print(value) end function func2(value) func(value) end function func3(value) func(value) endИмхо, не комильфо.А проблема со ссылкой, думаю, ясна - в таблице tbl, при использовании Register будет всегда одна и тот же ключ. От чего и попросил Вашего совета. Изменено 11 Июня 2013 пользователем ColR_iT Поделиться этим сообщением Ссылка на сообщение