Таблицы. Что это такое и с чем его едят. Часть 1. — различия между версиями — S.T.A.L.K.E.R. Inside Wiki

Таблицы. Что это такое и с чем его едят. Часть 1. — различия между версиями

Материал из S.T.A.L.K.E.R. Inside Wiki

Перейти к: навигация, поиск
(Обход элементов хэш-таблицы)
(оформил и сменил категорию..)
 
Строка 1: Строка 1:
 
Итак. Большинство модеров которые начинают осваивать скриптинг сталкера сталкиваются с таким понятием как таблицы.
 
Итак. Большинство модеров которые начинают осваивать скриптинг сталкера сталкиваются с таким понятием как таблицы.
 
==Таблицы==
 
==Таблицы==
Таблица в Lua – это не только базовый тип данных. И даже не столько. Это фундаментальная основа языка, предопределяющая чуть ли не все возможности Lua.<br>
+
Таблица в '''Lua''' – это не только базовый тип данных. И даже не столько. Это фундаментальная основа языка, предопределяющая чуть ли не все возможности Lua.<br>
 
Таблицы могут использоваться как обычные массивы, таблицы символов, множества, поля записей, деревья и так далее.<br>
 
Таблицы могут использоваться как обычные массивы, таблицы символов, множества, поля записей, деревья и так далее.<br>
 
Причем, поскольку функции относятся к значениям первого класса, поля таблицы могут содержать и функции. Таким образом, таблицы могут хранить методы.
 
Причем, поскольку функции относятся к значениям первого класса, поля таблицы могут содержать и функции. Таким образом, таблицы могут хранить методы.
Строка 8: Строка 8:
 
Например, вычисление знаменитой рекурсивной функции Аккермана на Lua на порядок быстрее, чем на Perl и Ruby, и в пять раз – чем на Python.<br>
 
Например, вычисление знаменитой рекурсивной функции Аккермана на Lua на порядок быстрее, чем на Perl и Ruby, и в пять раз – чем на Python.<br>
 
Скорость вычисления хэш-функций (с использованием механизма хэширования и строятся Lua-таблицы) у Lua почти безупречна – интерпретируемые Lua-программы справляются с этой задачей менее чем в два раза медленнее написанных на языке C.
 
Скорость вычисления хэш-функций (с использованием механизма хэширования и строятся Lua-таблицы) у Lua почти безупречна – интерпретируемые Lua-программы справляются с этой задачей менее чем в два раза медленнее написанных на языке C.
==Определение==
 
  
 +
==Определение==
 
Таблица представляет собой ассоциативный массив (набор пар ключ-значение). Ключём (индексом) и значением может быть любой тип данных, используемых в Lua (за исключением '''nil''').<br>
 
Таблица представляет собой ассоциативный массив (набор пар ключ-значение). Ключём (индексом) и значением может быть любой тип данных, используемых в Lua (за исключением '''nil''').<br>
  
Строка 16: Строка 16:
 
Поля отделяются друг от друга запятыми ("''','''") или точками с запятой ("''';'''"). При этом допускается наличие разделителя после последнего поля.
 
Поля отделяются друг от друга запятыми ("''','''") или точками с запятой ("''';'''"). При этом допускается наличие разделителя после последнего поля.
  
Таблица может быть проинициализирована при создании (стандартный конструктор таблицы) :  
+
Таблица может быть проинициализирована при создании (стандартный конструктор таблицы):
 +
<lua>t1 = {}                      -- пустая таблица
 +
t2 = { 1, 5, 7, 'abc' }      -- обычный массив
 +
t3 = { x = 7, y = "6" }      -- таблица с именованными полями '''x''' и '''y'''
 +
t4 = { 1, 'string', x = 77 } -- смешанная таблица
 +
t5 = { 1, xxx = 17, }        -- разделитель в конце допустим</lua>
  
t1 = {}                     -- пустая таблица
+
Или заполнена позже, инициализируя каждую пару ключ-значение:
t2 = { 1, 5, 7, 'abc' }      -- обычный массив
+
<lua>t4      = {}
t3 = { x = 7, y = "6" }      -- таблица с именованными полями '''x''' и '''y'''
+
t4[1]  = 1       -- Определяет число 1 на место, индексируемое номером 1
t4 = { 1, 'string', x = 77 } -- смешанная таблица
+
t4[2]  = 'string' -- Определяет строку 'string' на место, индексируемое номером 2
t5 = { 1, xxx = 17, }        -- разделитель в конце допустим
+
t4['x'] = 77       -- Определяет число 77 на место, индексируемое строкой 'x'</lua>
  
Или заполнена позже, инициализируя каждую пару ключ-значение :
+
Для удобства работы можно вместо индексирования таблицы по имени (строке) использовать это имя как имя поля структуры:
 
+
<lua>t4['x'] = 77
t4      = {}
+
t4.x    = 77</lua>
t4[1]  = 1        -- Определяет число 1 на место, индексируемое номером 1
+
t4[2]  = 'string' -- Определяет строку 'string' на место, индексируемое номером 2
+
t4['x'] = 77      -- Определяет число 77 на место, индексируемое строкой 'x'
+
 
+
Для удобства работы можно вместо индексирования таблицы по имени (строке) использовать это имя как имя поля структуры :
+
 
+
t4['x'] = 77
+
t4.x    = 77
+
  
 
Эти две формы обращения полностью эквивалентны.
 
Эти две формы обращения полностью эквивалентны.
  
 
==Массив==
 
==Массив==
 
 
Чтобы получить обычный массив (таблица t2) просто задаются значения элементов. Ключи будут установлены автоматически.<br>
 
Чтобы получить обычный массив (таблица t2) просто задаются значения элементов. Ключи будут установлены автоматически.<br>
 
В Lua обычные массивы индексируются целыми, последовательно-нарастающими числами начиная с единицы.
 
В Lua обычные массивы индексируются целыми, последовательно-нарастающими числами начиная с единицы.
 
Примеры ниже эквивалентны.
 
Примеры ниже эквивалентны.
 +
<lua>t2 = { 1, 5, 7, 'abc' }
  
t2 = { 1, 5, 7, 'abc' }
+
t2 = { [1]=1, [2]=5, [3]=7, [4]='abc' }
 
+
t2 = { [1]=1, [2]=5, [3]=7, [4]='abc' }
+
  
t2    = {}
+
t2    = {}
t2[1] = 1
+
t2[1] = 1
t2[2] = 5
+
t2[2] = 5
t2[3] = 7
+
t2[3] = 7
t2[4] = 'abc'
+
t2[4] = 'abc'</lua>
  
 
Пока возможно, Lua внутри себя таблицу хранит как массив, а не как хэш - таблицу.<br>
 
Пока возможно, Lua внутри себя таблицу хранит как массив, а не как хэш - таблицу.<br>
 
В этом случае доступ к элементам таблицы происходит почти так же быстро, как в массивах Си. Поэтому без особой нужды не нужно превращать массив в хэш.<br>
 
В этом случае доступ к элементам таблицы происходит почти так же быстро, как в массивах Си. Поэтому без особой нужды не нужно превращать массив в хэш.<br>
 
Для того, чтобы не нарушать структуру при добавлении и удалении элементов массива стоит пользоваться  библиотекой Lua '''table'''.
 
Для того, чтобы не нарушать структуру при добавлении и удалении элементов массива стоит пользоваться  библиотекой Lua '''table'''.
 
+
<lua>local t = {1, 2, 3, 4, 5}
local t = {1, 2, 3, 4, 5}
+
table.insert(t, 6)    -- добавляет элемент в конец массива.                                      t = {1, 2, 3, 4, 5, 6}
table.insert(t, 6)    -- добавляет элемент в конец массива.                                      t = {1, 2, 3, 4, 5, 6}
+
table.insert(t, 0, 1) -- вставляет элемент по индексу, сдвигая оставшиеся элементы массива.      t = {0, 1, 2, 3, 4, 5, 6}
table.insert(t, 0, 1) -- вставляет элемент по индексу, сдвигая оставшиеся элементы массива.      t = {0, 1, 2, 3, 4, 5, 6}
+
table.remove(t, 3)    -- удаляет из таблицы элемент по индексу 3 и сдвигает оставшиеся элементы. t = {0, 1, 3, 4, 5, 6}</lua>
table.remove(t, 3)    -- удаляет из таблицы элемент по индексу 3 и сдвигает оставшиеся элементы. t = {0, 1, 3, 4, 5, 6}
+
  
 
===Размер массива===
 
===Размер массива===
 
Получение размера массива выполняется оператором '''#''':
 
Получение размера массива выполняется оператором '''#''':
 
+
<lua>local count = #t</lua>
local count = #t
+
Оператор '''#''' возвращает целое число n, такое, что '''t[n]''' не '''nil''', и '''t[n + 1]''' равно '''nil'''. Другими словами оператор '''#''', возвращает  максимальный индекс непрерывной последовательности ключей от начала массива.<br>Соответственно, для таблицы:
 
+
<lua>t = {1, [100] = 2}</lua>
Оператор # возвращает целое число n, такое, что t[n] не nil, и t[n + 1] равно nil. Другими словами оператор #, возвращает  максимальный индекс непрерывной последовательности ключей от начала массива.<br>Соответственно, для таблицы:
+
длина будет равна 1, поскольку '''t[1]''' не '''nil''', а '''t[1 + 1]''' равно '''nil'''.
 
+
Для обычного массива, оператор '''#''' вернет количество элементов в массиве.
t = {1, [100] = 2}
+
 
+
длина будет равна 1, поскольку t[1] не nil, а t[1 + 1] равно nil.
+
Для обычного массива, оператор # вернет количество элементов в массиве.
+
  
 
===Обход элементов массива===
 
===Обход элементов массива===
 
 
Для обхода элементов массива используется как простая, так и расширенная форма записи оператора '''for''' (см. http://www.lua.ru/doc/2.4.5.html )
 
Для обхода элементов массива используется как простая, так и расширенная форма записи оператора '''for''' (см. http://www.lua.ru/doc/2.4.5.html )
Обычно применяется '''простая форма''' :
+
Обычно применяется '''простая форма''':
 
+
<lua>for i=1,#t do
for i=1,#t do
+
...
    ...
+
end</lua>
end
+
  
 
Цикл обойдет все поля массива от поля с индексом 1 (i=1) до последнего индекса поля (#t), определяемого оператором '''#''' (см. "Размер массива")<br>
 
Цикл обойдет все поля массива от поля с индексом 1 (i=1) до последнего индекса поля (#t), определяемого оператором '''#''' (см. "Размер массива")<br>
Или же '''расширенная форма''' с использованием функции-итератора '''ipairs''' :
+
Или же '''расширенная форма''' с использованием функции-итератора '''ipairs''':
 
+
<lua>for key,value in ipairs(t) do
for key,value in ipairs(t) do
+
...
    ...
+
end</lua>
end
+
  
Функция-итератор ipairs возвращает два значения. Первое - ключ этого поля, второе - значение.<br>
+
Функция-итератор '''ipairs''' возвращает два значения. Первое - ключ этого поля, второе - значение.<br>
 
При нахождении каждого последующего поля, эти значения присваиваются переменным '''key''' и '''value'''.
 
При нахождении каждого последующего поля, эти значения присваиваются переменным '''key''' и '''value'''.
  
 
==Хэш-таблицы==
 
==Хэш-таблицы==
 
+
Талицы, не попадающие под определение массива, являются хэш-таблицами. Индексами таких таблиц являются объекты различных типов (кроме '''nil''').<br>
Талицы, не попадающие под определение массива, являются хэш-таблицами. Индексами таких таблиц являются объекты различных типов (кроме nil).<br>
+
 
Узнать количество элементов такой таблицы, кроме как обойдя их все, нельзя.
 
Узнать количество элементов такой таблицы, кроме как обойдя их все, нельзя.
 +
 
===Строение хэш-таблицы===
 
===Строение хэш-таблицы===
 
Любая хэш-таблица состоит из двух частей - индексированной и именованной.
 
Любая хэш-таблица состоит из двух частей - индексированной и именованной.
 
Индексированная часть подчиняется законам массива (см. выше), именованная - включает индексы(ключи), которые невозможно включить в индексированную часть, не нарушая её строения.
 
Индексированная часть подчиняется законам массива (см. выше), именованная - включает индексы(ключи), которые невозможно включить в индексированную часть, не нарушая её строения.
Например для таблицы :
+
Например для таблицы:
t = {a=1,b=2}
+
<lua>t = {a=1,b=2}</lua>
существует индексированная часть. Подтвердить это можно вызвав оператор '#', предназначенный для определения длины :
+
существует индексированная часть. Подтвердить это можно вызвав оператор '#', предназначенный для определения длины:
print(#t) --> 0
+
<lua>print(#t) --> 0</lua>
Т.е. оператор '#' определил (хоть и нулевую, но) длину. Проверив таблицу :
+
Т.е. оператор '#' определил (хоть и нулевую, но) длину. Проверив таблицу:
t = {a=1,b=2, 'one'}
+
<lua>t = {a=1,b=2, 'one'}</lua>
 
Длина будет равна 1, т.к. появилось поле с индексом - [1], и значением - 'one' (автоматическое назначение индекса. см. выше)
 
Длина будет равна 1, т.к. появилось поле с индексом - [1], и значением - 'one' (автоматическое назначение индекса. см. выше)
 
Ни одно из двух других полей этой таблицы не может быть частью массива, вместе с полем [1]='one', т.к. их индексы не соответствуют индексу с номером [2].
 
Ни одно из двух других полей этой таблицы не может быть частью массива, вместе с полем [1]='one', т.к. их индексы не соответствуют индексу с номером [2].
Строка 114: Строка 101:
  
 
===Обход элементов хэш-таблицы===
 
===Обход элементов хэш-таблицы===
 
 
Обход осуществляется только '''расширенной формой''' оператора '''for''' с использование функции-итератора '''pairs'''.<br>
 
Обход осуществляется только '''расширенной формой''' оператора '''for''' с использование функции-итератора '''pairs'''.<br>
Эта функция позволяет обойти элементы любых таблиц (включая массивы). Возвращаемые значение такие-же, как и для функции ''ipairs'' :
+
Эта функция позволяет обойти элементы любых таблиц (включая массивы). Возвращаемые значение такие-же, как и для функции ''ipairs'':
 
+
<lua>for k,v in pairs(t) do
for k,v in pairs(t) do
+
...
    ...
+
end</lua>
end
+
  
 
При этом '''всегда''' сначала определяются поля индексированной части как массива, а затем именованной.
 
При этом '''всегда''' сначала определяются поля индексированной части как массива, а затем именованной.
Строка 128: Строка 113:
 
Хотя лично я не согласен с утверждением, что "ни при каких обстоятельствах не используйте внутри этого цикла удаление/добавление строк" и "следует использовать только для операций, не изменяющих структуру изменяемой таблицы!".
 
Хотя лично я не согласен с утверждением, что "ни при каких обстоятельствах не используйте внутри этого цикла удаление/добавление строк" и "следует использовать только для операций, не изменяющих структуру изменяемой таблицы!".
 
Правильнее было бы сказать, что "ни при каких обстоятельствах не изменяйте длину массива внутри этого цикла".
 
Правильнее было бы сказать, что "ни при каких обстоятельствах не изменяйте длину массива внутри этого цикла".
Т.е. "смертельный" вариант :
+
Т.е. "смертельный" вариант:
 +
<lua>for i = i, #t do
 +
table.remove(t,i)
 +
end</lua>
  
for i = i, #t do
+
в, котором с каждым "оборотом" уменьшается длина массива, становится самым быстрым и оптимальным в случае...ну, например, реверсирования массива:
    table.remove(t,i)
+
<lua>local len=#t
end
+
for i = len-1, 1, -1 do
 
+
t[len] = table.remove(t,i)
в, котором с каждым "оборотом" уменьшается длина массива, становится самым быстрым и оптимальным в случае...ну, например, реверсирования массива :
+
end</lua>
local len=#t
+
for i = len-1, 1, -1 do
+
    t[len] = table.remove(t,i)
+
end
+
 
в котором длина массива не изменяется.
 
в котором длина массива не изменяется.
  
Строка 150: Строка 134:
  
 
К примеру:
 
К примеру:
 +
<lua>local variables = {1, 2}</lua>
  
local variables = {1, 2}
+
''Примечание'': таблицы можно использовать как за функцией, так и внутри неё.
 
+
Примечание: таблицы можно использовать как за функцией, так и внутри неё.
+
 
В нашем случае таблица содержит набор чисел 1 и 2. Что же с ними можно сделать?
 
В нашем случае таблица содержит набор чисел 1 и 2. Что же с ними можно сделать?
 +
<lua>function table()
 +
local variables= {1, 2} --наша таблица
 +
rezultat = variables[math.random(table.getn(variables))] --rezultat локальная переменная.
 +
if rezultat == 1 then
 +
news_manager.send_tip(db.actor,lose_text, nil, nil, 10000) and db.actor:give_info_portion("lose")
 +
end
 +
if rezultat == 2 then
 +
news_manager.send_tip(db.actor,win_text, nil, nil, 10000) and db.actor:give_info_portion("win")
 +
end
 +
end</lua>
  
function table()
+
Поясню: '''variables[math.random(table.getn(variables))]''' этот оператор позволяет взять рандомное значение из данной таблицы. Тобишь случайно взять либо число 1, либо число 2.
local variables= {1, 2} --наша таблица
+
<lua>if rezultat == 1 then
rezultat = variables[math.random(table.getn(variables))] --rezultat локальная переменная.
+
news_manager.send_tip(db.actor,lose_text, nil, nil, 10000) and db.actor:give_info_portion("lose")
if rezultat == 1 then
+
end
news_manager.send_tip(db.actor,lose_text, nil, nil, 10000) and db.actor:give_info_portion("lose") end
+
if rezultat == 2 then
  if rezultat == 2 then
+
news_manager.send_tip(db.actor,win_text, nil, nil, 10000) and db.actor:give_info_portion("win")
news_manager.send_tip(db.actor,win_text, nil, nil, 10000) and db.actor:give_info_portion("win") end end
+
end</lua>
 
+
Поясню: variables[math.random(table.getn(variables))] этот оператор позволяет взять рандомное значение из данной таблицы. Тобишь случайно взять либо число 1, либо число 2.
+
 
+
  if rezultat == 1 then
+
news_manager.send_tip(db.actor,lose_text, nil, nil, 10000) and db.actor:give_info_portion("lose") end
+
  if rezultat == 2 then
+
news_manager.send_tip(db.actor,win_text, nil, nil, 10000) and db.actor:give_info_portion("win") end
+
 
Определяет значение взятое из таблицы, и в зависимости от результата присылает нам то или иное сообщение (news_manager.send_tip(db.actor,***, nil, nil, 10000)) и даёт тот или иной инфопоршень (db.actor:give_info_portion("***") end).
 
Определяет значение взятое из таблицы, и в зависимости от результата присылает нам то или иное сообщение (news_manager.send_tip(db.actor,***, nil, nil, 10000)) и даёт тот или иной инфопоршень (db.actor:give_info_portion("***") end).
  
  
'''=='''
+
'''==''' - это оператор сравнения. В нашем случае это "равно". Так же есть операторы:
 
+
Это оператор сравнения. В нашем случае это "равно". Так же есть операторы:
+
  
 
'''>''' - больше.
 
'''>''' - больше.
Строка 191: Строка 175:
  
 
На этом примере вы можете создать простейшую функцию спауна:
 
На этом примере вы можете создать простейшую функцию спауна:
 +
<lua>local stalker_types  = {"bread", "kolbasa", "conserva", "vodka"}
  
local stalker_types  = {"bread", "kolbasa", "conserva", "vodka"}
+
function spawn_item()  
 
+
alife():create(stalker_types[math.random(4)],vector():set(-0.112,0.477,-215.563),174943,265)
function spawn_item()  
+
end</lua>
alife():create(stalker_types[math.random(4)],vector():set(-0.112,0.477,-215.563),174943,265)
+
end
+
  
 
Как видите таблица используется вне функции, но можно и в самой функции. В данном примере в определённой точке с координатами (-0.112,0.477,-215.563),174943,265) заспаунится определённый предмет из списка. В эту таблицу можно внести как сталкеров, так и мутантов.
 
Как видите таблица используется вне функции, но можно и в самой функции. В данном примере в определённой точке с координатами (-0.112,0.477,-215.563),174943,265) заспаунится определённый предмет из списка. В эту таблицу можно внести как сталкеров, так и мутантов.
  
'''Позже продолжу. iDreD aka кровоSTALKER.'''
+
Автор: '''iDreD aka кровоSTALKER.'''
  
[[Категория:Незаконченные статьи]]
+
[[Категория: Скрипты]]

Текущая версия на 12:34, 23 сентября 2014

Итак. Большинство модеров которые начинают осваивать скриптинг сталкера сталкиваются с таким понятием как таблицы.

Таблицы

Таблица в Lua – это не только базовый тип данных. И даже не столько. Это фундаментальная основа языка, предопределяющая чуть ли не все возможности Lua.
Таблицы могут использоваться как обычные массивы, таблицы символов, множества, поля записей, деревья и так далее.
Причем, поскольку функции относятся к значениям первого класса, поля таблицы могут содержать и функции. Таким образом, таблицы могут хранить методы.

Механизмы реализации типа «таблица» или ассоциативный массив в Lua очень эффективны.
Например, вычисление знаменитой рекурсивной функции Аккермана на Lua на порядок быстрее, чем на Perl и Ruby, и в пять раз – чем на Python.
Скорость вычисления хэш-функций (с использованием механизма хэширования и строятся Lua-таблицы) у Lua почти безупречна – интерпретируемые Lua-программы справляются с этой задачей менее чем в два раза медленнее написанных на языке C.

Определение

Таблица представляет собой ассоциативный массив (набор пар ключ-значение). Ключём (индексом) и значением может быть любой тип данных, используемых в Lua (за исключением nil).

Конструктор таблицы

Конструктор используется для создания таблиц и представляет собой список полей в фигурных скобках.
Поля отделяются друг от друга запятыми (",") или точками с запятой (";"). При этом допускается наличие разделителя после последнего поля.

Таблица может быть проинициализирована при создании (стандартный конструктор таблицы):

t1 = {}                      -- пустая таблица
t2 = { 1, 5, 7, 'abc' }      -- обычный массив
t3 = { x = 7, y = "6" }      -- таблица с именованными полями '''x''' и '''y'''
t4 = { 1, 'string', x = 77 } -- смешанная таблица
t5 = { 1, xxx = 17, }        -- разделитель в конце допустим

Или заполнена позже, инициализируя каждую пару ключ-значение:

t4      = {}
t4[1]   = 1        -- Определяет число 1 на место, индексируемое номером 1
t4[2]   = 'string' -- Определяет строку 'string' на место, индексируемое номером 2
t4['x'] = 77       -- Определяет число 77 на место, индексируемое строкой 'x'

Для удобства работы можно вместо индексирования таблицы по имени (строке) использовать это имя как имя поля структуры:

t4['x'] = 77
t4.x    = 77

Эти две формы обращения полностью эквивалентны.

Массив

Чтобы получить обычный массив (таблица t2) просто задаются значения элементов. Ключи будут установлены автоматически.
В Lua обычные массивы индексируются целыми, последовательно-нарастающими числами начиная с единицы. Примеры ниже эквивалентны.

t2 = { 1, 5, 7, 'abc' }
 
t2 = { [1]=1, [2]=5, [3]=7, [4]='abc' }
 
t2    = {}
t2[1] = 1
t2[2] = 5
t2[3] = 7
t2[4] = 'abc'

Пока возможно, Lua внутри себя таблицу хранит как массив, а не как хэш - таблицу.
В этом случае доступ к элементам таблицы происходит почти так же быстро, как в массивах Си. Поэтому без особой нужды не нужно превращать массив в хэш.
Для того, чтобы не нарушать структуру при добавлении и удалении элементов массива стоит пользоваться библиотекой Lua table.

local t = {1, 2, 3, 4, 5}
table.insert(t, 6)    -- добавляет элемент в конец массива.                                      t = {1, 2, 3, 4, 5, 6}
table.insert(t, 0, 1) -- вставляет элемент по индексу, сдвигая оставшиеся элементы массива.      t = {0, 1, 2, 3, 4, 5, 6}
table.remove(t, 3)    -- удаляет из таблицы элемент по индексу 3 и сдвигает оставшиеся элементы. t = {0, 1, 3, 4, 5, 6}

Размер массива

Получение размера массива выполняется оператором #:

local count = #t

Оператор # возвращает целое число n, такое, что t[n] не nil, и t[n + 1] равно nil. Другими словами оператор #, возвращает максимальный индекс непрерывной последовательности ключей от начала массива.
Соответственно, для таблицы:

t = {1, [100] = 2}

длина будет равна 1, поскольку t[1] не nil, а t[1 + 1] равно nil. Для обычного массива, оператор # вернет количество элементов в массиве.

Обход элементов массива

Для обхода элементов массива используется как простая, так и расширенная форма записи оператора for (см. http://www.lua.ru/doc/2.4.5.html ) Обычно применяется простая форма:

for i=1,#t do
...
end

Цикл обойдет все поля массива от поля с индексом 1 (i=1) до последнего индекса поля (#t), определяемого оператором # (см. "Размер массива")
Или же расширенная форма с использованием функции-итератора ipairs:

for key,value in ipairs(t) do
...
end

Функция-итератор ipairs возвращает два значения. Первое - ключ этого поля, второе - значение.
При нахождении каждого последующего поля, эти значения присваиваются переменным key и value.

Хэш-таблицы

Талицы, не попадающие под определение массива, являются хэш-таблицами. Индексами таких таблиц являются объекты различных типов (кроме nil).
Узнать количество элементов такой таблицы, кроме как обойдя их все, нельзя.

Строение хэш-таблицы

Любая хэш-таблица состоит из двух частей - индексированной и именованной. Индексированная часть подчиняется законам массива (см. выше), именованная - включает индексы(ключи), которые невозможно включить в индексированную часть, не нарушая её строения. Например для таблицы:

t = {a=1,b=2}

существует индексированная часть. Подтвердить это можно вызвав оператор '#', предназначенный для определения длины:

print(#t) --> 0

Т.е. оператор '#' определил (хоть и нулевую, но) длину. Проверив таблицу:

t = {a=1,b=2, 'one'}

Длина будет равна 1, т.к. появилось поле с индексом - [1], и значением - 'one' (автоматическое назначение индекса. см. выше) Ни одно из двух других полей этой таблицы не может быть частью массива, вместе с полем [1]='one', т.к. их индексы не соответствуют индексу с номером [2]. Поэтому :

  • часть 'one' будет индексированной частью.
  • часть a=1 и b=2 именованной

Обход элементов хэш-таблицы

Обход осуществляется только расширенной формой оператора for с использование функции-итератора pairs.
Эта функция позволяет обойти элементы любых таблиц (включая массивы). Возвращаемые значение такие-же, как и для функции ipairs:

for k,v in pairs(t) do
...
end

При этом всегда сначала определяются поля индексированной части как массива, а затем именованной.

Об ошибках, связанных с циклами по таблицам см. в статье KamikaZze здесь

Хотя лично я не согласен с утверждением, что "ни при каких обстоятельствах не используйте внутри этого цикла удаление/добавление строк" и "следует использовать только для операций, не изменяющих структуру изменяемой таблицы!". Правильнее было бы сказать, что "ни при каких обстоятельствах не изменяйте длину массива внутри этого цикла". Т.е. "смертельный" вариант:

for i = i, #t do
table.remove(t,i)
end

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

local len=#t
for i = len-1, 1, -1 do
t[len] = table.remove(t,i)
end

в котором длина массива не изменяется.

to be continue ...

Nazgool

P.S. То, что ниже, это остатки первоначальной статьи, верхнюю часть которой я безжалостно вырезал за несоответствие названию статьи.


К примеру:

local variables = {1, 2}

Примечание: таблицы можно использовать как за функцией, так и внутри неё. В нашем случае таблица содержит набор чисел 1 и 2. Что же с ними можно сделать?

function table()
local variables= {1, 2} --наша таблица
rezultat = variables[math.random(table.getn(variables))] --rezultat локальная переменная.
if rezultat == 1 then
news_manager.send_tip(db.actor,lose_text, nil, nil, 10000) and db.actor:give_info_portion("lose")
end
if rezultat == 2 then
news_manager.send_tip(db.actor,win_text, nil, nil, 10000) and db.actor:give_info_portion("win") 
end
end

Поясню: variables[math.random(table.getn(variables))] этот оператор позволяет взять рандомное значение из данной таблицы. Тобишь случайно взять либо число 1, либо число 2.

if rezultat == 1 then
news_manager.send_tip(db.actor,lose_text, nil, nil, 10000) and db.actor:give_info_portion("lose")
end
if rezultat == 2 then
news_manager.send_tip(db.actor,win_text, nil, nil, 10000) and db.actor:give_info_portion("win")
end

Определяет значение взятое из таблицы, и в зависимости от результата присылает нам то или иное сообщение (news_manager.send_tip(db.actor,***, nil, nil, 10000)) и даёт тот или иной инфопоршень (db.actor:give_info_portion("***") end).


== - это оператор сравнения. В нашем случае это "равно". Так же есть операторы:

> - больше.

< - меньше.

>= - больше или равно.

<= - меньше или равно.

~= - не равно.


Сравнивать можно только числа или локальные переменные с присвоенными к ним числами.

На этом примере вы можете создать простейшую функцию спауна:

local stalker_types  = {"bread", "kolbasa", "conserva", "vodka"}
 
function spawn_item() 
alife():create(stalker_types[math.random(4)],vector():set(-0.112,0.477,-215.563),174943,265)
end

Как видите таблица используется вне функции, но можно и в самой функции. В данном примере в определённой точке с координатами (-0.112,0.477,-215.563),174943,265) заспаунится определённый предмет из списка. В эту таблицу можно внести как сталкеров, так и мутантов.

Автор: iDreD aka кровоSTALKER.

Другие места
LANGUAGE