<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[QUIK -> DDE &mdash; Работа цикла for в Lua]]></title>
	<link rel="self" href="https://quik2dde.ru/extern.php?action=feed&amp;tid=62&amp;type=atom" />
	<updated>2015-02-10T07:05:24Z</updated>
	<generator>PunBB</generator>
	<id>https://quik2dde.ru/viewtopic.php?id=62</id>
		<entry>
			<title type="html"><![CDATA[Re: Работа цикла for в Lua]]></title>
			<link rel="alternate" href="https://quik2dde.ru/viewtopic.php?pid=1006#p1006" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>swerg пишет:</cite><blockquote><p>Посмотрим, какие практические выводы можно сделать на основании написанного в предыдущем посте.</p></blockquote></div><p>вот так проще:<br /></p><div class="codebox"><pre><code>t={1,2,3,3,5}
DEL_ITEM=3
tt=t
for i=1,#tt do
    if i == DEL_ITEM then
        table.remove(t,i)
    end
end
print(#t)--&gt;4
s=&quot;&quot;
for i=1,#t do
    s=s .. t[i] ..&#039;,&#039;
end
print(s)--&gt;1,2,3,5,</code></pre></div>]]></content>
			<author>
				<name><![CDATA[kalikazandr]]></name>
				<uri>https://quik2dde.ru/profile.php?id=208</uri>
			</author>
			<updated>2015-02-10T07:05:24Z</updated>
			<id>https://quik2dde.ru/viewtopic.php?pid=1006#p1006</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: Работа цикла for в Lua]]></title>
			<link rel="alternate" href="https://quik2dde.ru/viewtopic.php?pid=729#p729" />
			<content type="html"><![CDATA[<p>Очень интересный пример! Спасибо!</p>]]></content>
			<author>
				<name><![CDATA[Metallurg]]></name>
				<uri>https://quik2dde.ru/profile.php?id=226</uri>
			</author>
			<updated>2015-01-07T18:00:39Z</updated>
			<id>https://quik2dde.ru/viewtopic.php?pid=729#p729</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: Работа цикла for в Lua]]></title>
			<link rel="alternate" href="https://quik2dde.ru/viewtopic.php?pid=402#p402" />
			<content type="html"><![CDATA[<p>Посмотрим, какие практические выводы можно сделать на основании написанного в предыдущем посте.</p><p>Пусть есть задача написать программу, которая бы удаляла из таблицы элементы с определенным значением. Казалось бы, все просто:<br /></p><div class="codebox"><pre><code>t = {1,2,3,3,5}
DEL_ITEM = 3

s = &quot;&quot;
-- удалим элементы, равные DEL_ITEM
for i = 1,#t do
  s = s .. tostring(t[i]) .. &quot;,&quot;
  if t[i] == DEL_ITEM then
    table.remove(t, i)
  end
end

message(&quot;process:&quot; .. s, 1)

s = &quot;&quot;
-- выведем все оставшиеся элементы
for i = 1,#t do
  s = s .. tostring(t[i]) .. &quot;,&quot;
end

message(&quot;result:&quot; .. s, 2)</code></pre></div><p>Запускаем эту программу в QUIK и видим следующие результаты:<br /></p><div class="quotebox"><blockquote><p>process:1,2,3,5,nil,<br />result:1,2,3,5,</p></blockquote></div><p>Во-первых, как видно, после работы программы в таблице остался один элемент, равный 3, т.е. не все требуемые элементы удалились. А во-вторых, мы еще и обрабатывали элемент со значением <strong>nil</strong>! И все потому, что границы для for были вычислены один раз, после чего мы получили последовательную итерацию элементов от 1 до 5, не смотря на то, что после удаления элемента из таблицы количество их уменьшилось.<br />Наш простой пример пережил обработку nil-элемента, конечно, безболезненно, в реальной программе все может оказаться не так радужно.</p><p>В принципе, поправить программу для удаления элементов с определенным значением очень просто: достаточно лишь изменить обхода перебора элементов в цикле for, перебирая не от первого к последнему, а наоборот, от последнего к первому. Вот как это выглядит (по сравнению с предыдущим кодом изменена всего одна строчка с первым for):</p><div class="codebox"><pre><code>t = {1,2,3,3,5}
DEL_ITEM = 3

s = &quot;&quot;
-- удалим элементы, равные DEL_ITEM
for i = #t,1,-1 do
  s = s .. tostring(t[i]) .. &quot;,&quot;
  if t[i] == DEL_ITEM then
    table.remove(t, i)
  end
end

message(&quot;process:&quot; .. s, 1)

s = &quot;&quot;
-- выведем все оставшиеся элементы
for i = 1,#t do
  s = s .. tostring(t[i]) .. &quot;,&quot;
end

message(&quot;result:&quot; .. s, 2)</code></pre></div><p>Запускаем эту программу в QUIK и видим следующие результаты:<br /></p><div class="quotebox"><blockquote><p>process:5,3,3,2,1<br />result:1,2,5,</p></blockquote></div><p>Видно, в этом случае мы не обрабатываем &quot;левый&quot; элемент (со значеним nil), кроме того работа алгоритма совершенно корректна: все элементы со значением 3 удалены.</p><p><span class="bbu"><strong>Вывод</strong></span>: при использовании <strong>цикла for</strong> в варианте &quot;со счетчиком&quot; всегда необходимо подумать: не изменяет тело цикла границы (размер) обрабатываемой сущности. Если размер изменяется - необходимо продумать, как в этом случае поведет себя наш алгоритм и, возможно, реорганизовать его так, чтобы не возникало обращений к несуществующим элементам.</p>]]></content>
			<author>
				<name><![CDATA[swerg]]></name>
				<uri>https://quik2dde.ru/profile.php?id=78</uri>
			</author>
			<updated>2013-08-04T15:26:49Z</updated>
			<id>https://quik2dde.ru/viewtopic.php?pid=402#p402</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Работа цикла for в Lua]]></title>
			<link rel="alternate" href="https://quik2dde.ru/viewtopic.php?pid=392#p392" />
			<content type="html"><![CDATA[<p>В организации работы цикла for в разных языках программирования есть одно существенное различие: где-то граничные условия вычисляются 1 раз (например, Delphi), где-то условие перевычисляется каждый раз после каждой итерации (например, C). А как с этим обстоят дела в Lua?</p><p>Для проверки загрузил в QUIK следующий простенький скрипт:</p><div class="codebox"><pre><code>function GetFirstVal ()
    message(&quot;GetFirstVal ()&quot;, 2)
    return 1
end

function GetLastVal()
    message(&quot;GetLastVal()&quot;, 2)
    return 3
end

message(&quot;---Start---&quot;, 1)

for i = GetFirstVal(), GetLastVal() do
    message(tostring(i), 1)
end</code></pre></div><p>Запустив его, получаем следующую последовательность вывода сообщений:</p><p>---Start---<br />GetFirstVal()<br />GetLastVal()<br />1<br />2<br />3</p><p>Таким образом видно, что условие окончания цикла вычисляется только <strong>один</strong> раз, после чего цикл всегда отрабатывает это количество итераций (за исключением применения break, конечно).</p>]]></content>
			<author>
				<name><![CDATA[swerg]]></name>
				<uri>https://quik2dde.ru/profile.php?id=78</uri>
			</author>
			<updated>2013-07-28T12:34:12Z</updated>
			<id>https://quik2dde.ru/viewtopic.php?pid=392#p392</id>
		</entry>
</feed>
