Всем доброго времени суток.
В Lua есть две удобные вещи: pairs и ipairs, предназначенные для использования с таблицами.
pairs для таблиц - ассоциативных массивов (ключ - значение). Точнее сказать, pairs обычно используется с ассоциативными массивами, но и с обычными таблицами-массивами тоже работает.
ipairs для таблиц - обычных массивов (упорядоченные элементы с последовательными индексами от 1 до <количество_элементов_таблицы>). По сути, разница (относительно pairs) в том, что ключ "целочисленный", начинается с единицы и по возрастающей с шагом 1.
for i, v in pairs(t) do
print(i) -- выдаст ключ
print(v) -- выдаст значение
end> t = { ["A"] = "a", ["B"] = "b", ["C"] = "c"}
> for i, v in pairs(t) do
>> print(i)
>> print(v)
>> end
B
b
C
c
A
afor i, v in ipairs(t) do
print(i) -- выдаст индекс элемента
print(v) -- выдаст сам элемент
end> t = { "a", "b", "c", "d" }
> for i, v in ipairs(t) do
>> print(i)
>> print(v)
>> end
1
a
2
b
3
c
4
dВсе вроде бы понятно. Но, как обычно и бывает, способ написанный в документации - не единственный. И чтобы обойти таблицу-массив можно воспользоваться другим вариантом:
-- #t = длина таблицы t
for i = 1, #t do
print(t[i]) -- выдаст элемент
end> for i = 1, #t do
>> print(t[i])
>> end
a
b
c
dВ Lua 5.2 (в других не проверял) если провести сравнительный тест, то становится наглядно видно, чтобы цикла вида for i = 1, #t отрабатывает раза в 1.5-2 быстрее, чем for i, v in ipairs(t).
Откуда берется разница - вроде понятно, for i = 1, #t просто перебирает i с шагом 1, а for i, v in ipairs(t) именно получает значение и индекса, и элемента, по тому и отрабатывает медленней.
Вопрос в следующем, на какие подводные камни можно наткнутся, если использовать for i = 1, #t для обхода таблицы-массива вместо for i, v in ipairs(t). По тому что хоть for i, v in ipairs(t) вроде и правильней, жертвовать скоростью совсем не хочется.
Понятно, что если в цикле предстоит удалять элементы, то for i = 1, #t использовать нельзя
-- на момент начала цикла #t - какое-то конкретное значение типа number
for i = 1, #t do
if (t[i] == "str") then
-- как только удалим элемент, размер таблицы изменится,
-- а значит цикл выйдет за пределы таблицы и будет ошибка
table.remove(t, i)
end
endА помимо удаления и подобных операций, когда таблица в ходе цикла будет заметно изменена, есть еще какие-то ситуации, когда использование for i = 1, #t do чревато проблемами?
И вообще, что посоветуете: не брезгать "быдлокодить" с for i = 1, #t do раз это дает профит по скорости работы, либо же строго придерживаться ipairs() по тому что "так положено" ?
