Удаление элемента из массива, который прошёл проверку

Страницы: 1
RSS
Удаление элемента из массива, который прошёл проверку
 
Здравствуйте!
Не получается решить проблему с удалением элемента из массива, который прошёл проверку.
Пробовал и поиск и разные способы, но ничего не помогло.

Нужно чтобы после выполнения условия "if Raznica > 1 then" выводилось сообщение и данный элемент (в моём случае в цикле это "bumaga") больше не входил в проверку и повторно не выводилось сообщение.
Нужно убрать этот элемент из sec_code = { ... }, т.е. удалить конкретный элемент из массива sec_code

Понял лишь то, что после message ... нужно использовать "table.remove", что то вроде:
Код
   if Raznica > 1 then
   message(tostring(bumaga .. " " .. Raznica ))
   table.remove (sec_code, 1)
   sleep(3000)
но указать удаление конкретной акции (прошедшей проверку) в массиве не получается.


Надеюсь понятно изложил проблему. Начинающий говнокодер :) Может кто помочь советом?

Код
IsRun = true
sec_code = { "GAZAP", "LKOH", "SBER", "GMKN", "TRFM", "RAVN" }
class_code = "QJSIM"

function main()
   while IsRun do
      for _,bumaga in ipairs(sec_code) do
      LowDnya = getParamEx (class_code, bumaga, "LOW").param_value
      Last = getParamEx (class_code, bumaga, "LAST").param_value
      Raznica = math.abs(LowDnya - Last)
         if Raznica > 1 then
         message(tostring(bumaga .. " " .. Raznica ))
         sleep(3000)
         end
      end   
   end
end

function OnStop()
   IsRun = false
end
 
Цитата
Hired написал:
Понял лишь то, что после message ... нужно использовать "table.remove",
Концептуально да, практически удалять элементы из массива, по которому идет итерация, не стоит. Предлагаю другой вариант: перед циклом for создайте временный пустой массив, назовем его temp_sec_code, в цикле проверяете элемент и либо кладете его в новый массив, либо показываете сообщение. Таким образом, во временном массиве у вас бумаги, по которым сообщение еще не показано. По окончании цикла for просто sec_code = temp_sec_code.
 
Вариант 1:
Код
    for i, bumaga in pairs(sec_code) do
      LowDnya = getParamEx (class_code, bumaga, "LOW").param_value
      Last = getParamEx (class_code, bumaga, "LAST").param_value
      Raznica = math.abs(LowDnya - Last)
      if Raznica > 1 then
        message(tostring(bumaga .. " " .. Raznica ))
        sec_code[i] = nil
      end
    end

Вариант 2:
Код
    for i = #sec_code, 1, -1 do
      local bumaga = sec_code[i]
      LowDnya = getParamEx (class_code, bumaga, "LOW").param_value
      Last = getParamEx (class_code, bumaga, "LAST").param_value
      Raznica = math.abs(LowDnya - Last)
      if Raznica > 1 then
        message(tostring(bumaga .. " " .. Raznica ))
        table.remove(sec_code, i)
      end
    end
Надо делать так, как надо. А как не надо - делать не надо.
 
примерно так:
...
     for k,bumaga in ipairs(sec_code) do
     LowDnya = getParamEx (class_code, bumaga, "LOW").param_value
     Last = getParamEx (class_code, bumaga, "LAST").param_value
     Raznica = math.abs(LowDnya - Last)
        if Raznica > 1 then
        message(tostring(bumaga .. " " .. Raznica ))
          table.remove((sec_code,k)
        sleep(3000)
        end
     end  
 
 
...
         table.remove(sec_code,k)
...
 
Цитата
Николай Камынин написал:
примерно так:
Это из серии вредных советов. Так делать не следует.
Надо делать так, как надо. А как не надо - делать не надо.
 
Добрый день.

Hired, Вам удалось решить проблему?
 
Эту задачу можно решить разными способами.

1. Усложняете таблицу элементов. Вместо элементов - вложенные таблицы, с полями  sec_code и checked. После проверки ставите checked = true. Далее по условию проверяете, что элемент уже не трубует проверки.
   Недостаток - более сложная струтуруа, постоянно занятая памаять полной таблицей.
2. Вводите новую таблицу, уже проверенных элементов, и по условию вхождения в эту таблицу проверяете, что элемент уже не трубует проверки.
   Недостаток - рост занятой памяти, т.к. надо вводить новую сущность.
3. Как уже написали выше - ввести временную таблицу с нужными элементами, а в конце перейти на эту таблицу.
4. Перебор через while, удаление через table.sremove. Именно, через потокбезопасную функцию, хоть у Вас в коде и нет второго потока, использующего эту таблицу.
Почему через for делать нельзя ни в коем случае. Потому что цикл for вычисляет свои значения один раз перед стартом цикла. Поэтому он будет помнить число элементов в таблице, что было изначально - это его инвариантное состояние.
Поэтому while. И аккуратно сдвигать счетчик текущего элемента. Этот вариант самый нежелательный, хоть и рабочий.
 
Цитата
Старатель написал:
Вариант 2:
Код
    for i = #sec_code, 1, -1 do
      local bumaga = sec_code
      LowDnya = getParamEx (class_code, bumaga, "LOW").param_value
      Last = getParamEx (class_code, bumaga, "LAST").param_value
      Raznica = math.abs(LowDnya - Last)
      if Raznica > 1 then
        message(tostring(bumaga .. " " .. Raznica ))
        table.remove(sec_code, i)
      end
    end
Спасибо! Этот способ сработал! Проблема решена. Всё оказалось проще, чем я думал :)

Цитата
Nikolay написал:
Эту задачу можно решить разными способами.
Цитата
Anton написал:
Предлагаю другой вариант: перед циклом for создайте временный пустой массив
Спасибо за советы! В будущем обязательно попробую предложенные варианты в более сложных скриптах!
 
Цитата
Egor Zaytsev написал:
Добрый день.

Hired , Вам удалось решить проблему?
Проблема решена. Спасибо всем отписавшимся!
 
Цитата
Старатель написал:
Вариант 1:
Вариант 1 неожиданно может дать ошибку, т.ч. лучше пользоваться вариантом 2 или делать обход через next
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Старатель написал:
Вариант 1 неожиданно может дать  ошибку
Прошу прощения. Та ошибка касается только ассоциативных массивов.
В текущей постановке задачи, когда таблица с целочисленными ключами, можно использовать оба варианта.
Надо делать так, как надо. А как не надо - делать не надо.
Страницы: 1
Читают тему
Наверх