vcat StackOverflowError in julia - julia
I have written a function to detect objects in arrays. In this case I use it to clear white objects, which touch the border of an image. But the problem is, that there is always a StackOverFlowError in vcat and it occurs at different lines (depends on image). Here is a minimum working example. It works fine with the second image, but not with the first:
using Images
function getImChars(I::Array)
charAr=copy(I);
indexMax=find(x->(x==1),charAr);
(h,w)=size(charAr);
# check border values
(r,c)=ind2sub(size(charAr),indexMax);
indexBorderR1=find(x->(x==1),r);
indexBorderR2=find(x->(x==h),r);
indexBorderR=[indexBorderR1;indexBorderR2];
indexBorderC1=find(x->(x==1),c);
indexBorderC2=find(x->(x==w),c);
indexBorderC=[indexBorderC1;indexBorderC2];
borderPixels=[999;999]; # initialize def value FIX
for bRc=1:length(indexBorderR)
borderPixels=[borderPixels [r[indexBorderR[bRc]];c[indexBorderR[bRc]]]];
end
for bCc=1:length(indexBorderC)
borderPixels=[borderPixels [r[indexBorderC[bCc]];c[indexBorderC[bCc]]]];
end
borderPixels=borderPixels[:,2:end];
(rbP,cbP)=size(borderPixels);
fcharAr=[];
for k=1:cbP
bP=[borderPixels[:,k];false;false;false;false];
locObj1=[];
locObj2=[];
locObj3=[];
locObj4=[];
locObj5=[];
locObj6=[];
if(charAr[bP[1],bP[2]]==0)
continue;
else
charAr[bP[1],bP[2]]=0;
end
recGetCharClearBorders(true,false,h,w,bP,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,charAr);
end
return charAr;
end
function recGetCharClearBorders(firstFlag::Bool,doNotAdd::Bool,h::Int,w::Int,hP::Array,locObj1::Array,locObj2::Array,locObj3::Array,locObj4::Array,locObj5::Array,locObj6::Array,imAr::Array)
leftPoint=[hP[1];hP[2]-1;0;0;0;0];
rightPoint=[hP[1];hP[2]+1;0;0;0;0];
topPoint=[hP[1]-1;hP[2];0;0;0;0];
bottomPoint=[hP[1]+1;hP[2];0;0;0;0];
# check if it is not out of bounds and relative directions
if(topPoint[1]!=0)
if(imAr[topPoint[1],topPoint[2]]==1)
hP[4]=1;
end
end
if(bottomPoint[1]!=(h+1))
if(imAr[bottomPoint[1],bottomPoint[2]]==1)
hP[6]=1;
end
end
if(leftPoint[2]!=0)
if(imAr[leftPoint[1],leftPoint[2]]==1)
hP[3]=1;
end
end
if(rightPoint[2]!=(w+1))
if(imAr[rightPoint[1],rightPoint[2]]==1)
hP[5]=1;
end
end
# add first elements
if(firstFlag)
locObj1=collect(hP[1]);
locObj2=collect(hP[2]);
locObj3=collect(hP[3]);
locObj4=collect(hP[4]);
locObj5=collect(hP[5]);
locObj6=collect(hP[6]);
firstFlag=false;
else
# if first element of locObj was deleted actual point should not get pushed to array
if(!doNotAdd)
push!(locObj1,hP[1]);
push!(locObj2,hP[2]);
push!(locObj3,hP[3]);
push!(locObj4,hP[4]);
push!(locObj5,hP[5]);
push!(locObj6,hP[6]);
imAr[hP[1],hP[2]]=0;
end
end
goL=false;
goT=false;
goR=false;
goB=false;
doNotAdd=false;
if(length(locObj1)!=0)
# always take and check first elements of locObj
hPfInLoc=[locObj1[1],locObj2[1],locObj3[1],locObj4[1],locObj5[1],locObj6[1]];
hPl=[hPfInLoc[1];hPfInLoc[2]-1;0;0;0;0];
hPt=[hPfInLoc[1]-1;hPfInLoc[2];0;0;0;0];
hPr=[hPfInLoc[1];hPfInLoc[2]+1;0;0;0;0];
hPb=[hPfInLoc[1]+1;hPfInLoc[2];0;0;0;0];
compL=false;
compT=false;
compR=false;
compB=false;
# check bounds and if array values have changed
if(hPt[1]!=0)
if(imAr[hPt[1],hPt[2]]!=0)
compT=true;
end
end
if(hPb[1]!=(h+1))
if(imAr[hPb[1],hPb[2]]!=0)
compB=true;
end
end
if(hPl[2]!=0)
if(imAr[hPl[1],hPl[2]]!=0)
compL=true;
end
end
if(hPr[2]!=(w+1))
if(imAr[hPr[1],hPr[2]]!=0)
compR=true;
end
end
# define directions and set defined direction false in locObj
if((locObj3[1]==1)& compL)
locObj3[1]=0;
goL=true;
elseif((locObj4[1]==1)& compT)
locObj4[1]=0;
goT=true;
elseif((locObj5[1]==1)& compR)
locObj5[1]=0;
goR=true;
elseif((locObj6[1]==1)& compB)
locObj6[1]=0;
goB=true;
else
if (length(locObj1)==1)
locObj=[];
else # if everything is zero delete first rows of arrays
deleteat!(locObj1,1);
deleteat!(locObj2,1);
deleteat!(locObj3,1);
deleteat!(locObj4,1);
deleteat!(locObj5,1);
deleteat!(locObj6,1);
doNotAdd=true;
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hP,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
end
end
#execute choosen direction
if(goL)
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hPl,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
if(goT)
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hPt,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
if(goR)
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hPr,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
if(goB)
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hPb,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
end
# execute test procedure
Im=Images.load("Test.png");
Im=data(Im);
imAr=map(Float64,Im);
resIm=getImChars(imAr);
save("Imout.png",resIm);
You only have to change the name of the image in my code. Just tell me, if you need some more information. Thanks a lot.
Cheers, clax
Unlike many functional programming language, Julia doesn't optimize for tail recursion (reusing the stack frame when a function ends by a call). So in your case it is very likely that your recursive function hits the max stack depths depending on your OS's thread stack size.
Unfortunately, the Julia core team decide not to prioritise Tail call optimization as they don't deem such feature a must. Indeed people can often refactor their code into loops.
Afaik, tail call optimization is pretty difficult and many other programming languages featuring functional programming paradigm also lack it.
Took a few minutes needed to run and fixup the tail recursion. Is the following replacement for recGetCharClearBorders performing correctly:
function recGetCharClearBorders(firstFlag::Bool,doNotAdd::Bool,h::Int,w::Int,hP::Array,locObj1::Array,locObj2::Array,locObj3::Array,locObj4::Array,locObj5::Array,locObj6::Array,imAr::Array,recdepth,recloc)
while true
leftPoint=[hP[1];hP[2]-1;0;0;0;0];
rightPoint=[hP[1];hP[2]+1;0;0;0;0];
topPoint=[hP[1]-1;hP[2];0;0;0;0];
bottomPoint=[hP[1]+1;hP[2];0;0;0;0];
# check if it is not out of bounds and relative directions
if(topPoint[1]!=0)
if(imAr[topPoint[1],topPoint[2]]==1)
hP[4]=1;
end
end
if(bottomPoint[1]!=(h+1))
if(imAr[bottomPoint[1],bottomPoint[2]]==1)
hP[6]=1;
end
end
if(leftPoint[2]!=0)
if(imAr[leftPoint[1],leftPoint[2]]==1)
hP[3]=1;
end
end
if(rightPoint[2]!=(w+1))
if(imAr[rightPoint[1],rightPoint[2]]==1)
hP[5]=1;
end
end
# add first elements
if(firstFlag)
locObj1=collect(hP[1]);
locObj2=collect(hP[2]);
locObj3=collect(hP[3]);
locObj4=collect(hP[4]);
locObj5=collect(hP[5]);
locObj6=collect(hP[6]);
firstFlag=false;
else
# if first element of locObj was deleted actual point should not get pushed to array
if(!doNotAdd)
push!(locObj1,hP[1]);
push!(locObj2,hP[2]);
push!(locObj3,hP[3]);
push!(locObj4,hP[4]);
push!(locObj5,hP[5]);
push!(locObj6,hP[6]);
imAr[hP[1],hP[2]]=0;
end
end
goL=false;
goT=false;
goR=false;
goB=false;
doNotAdd=false;
if(length(locObj1)!=0)
# always take and check first elements of locObj
hPfInLoc=[locObj1[1],locObj2[1],locObj3[1],locObj4[1],locObj5[1],locObj6[1]];
hPl=[hPfInLoc[1];hPfInLoc[2]-1;0;0;0;0];
hPt=[hPfInLoc[1]-1;hPfInLoc[2];0;0;0;0];
hPr=[hPfInLoc[1];hPfInLoc[2]+1;0;0;0;0];
hPb=[hPfInLoc[1]+1;hPfInLoc[2];0;0;0;0];
compL=false;
compT=false;
compR=false;
compB=false;
# check bounds and if array values have changed
if(hPt[1]!=0)
if(imAr[hPt[1],hPt[2]]!=0)
compT=true;
end
end
if(hPb[1]!=(h+1))
if(imAr[hPb[1],hPb[2]]!=0)
compB=true;
end
end
if(hPl[2]!=0)
if(imAr[hPl[1],hPl[2]]!=0)
compL=true;
end
end
if(hPr[2]!=(w+1))
if(imAr[hPr[1],hPr[2]]!=0)
compR=true;
end
end
# define directions and set defined direction false in locObj
if((locObj3[1]==1)& compL)
locObj3[1]=0;
goL=true;
elseif((locObj4[1]==1)& compT)
locObj4[1]=0;
goT=true;
elseif((locObj5[1]==1)& compR)
locObj5[1]=0;
goR=true;
elseif((locObj6[1]==1)& compB)
locObj6[1]=0;
goB=true;
else
if (length(locObj1)==1)
locObj=[];
else # if everything is zero delete first rows of arrays
deleteat!(locObj1,1);
deleteat!(locObj2,1);
deleteat!(locObj3,1);
deleteat!(locObj4,1);
deleteat!(locObj5,1);
deleteat!(locObj6,1);
doNotAdd=true;
continue
end
end
end
#execute choosen direction
if(goL)
hP = hPl
continue
end
if(goT)
hP = hPt
continue
end
if(goR)
hP = hPr
continue
end
if(goB)
hP = hPb
continue
end
break
end
end
Somehow the output image turned on its side in my run.
Related
Cycle between minimized windows while preserving position
So I have this keybind: awful.key({modkey}, ";", function() if client.focus then for c in awful.client.iterate(function(x) return x.minimized end) do c.minimized = false client.focus.minimized = true client.focus = c client.focus:raise() break end end end The aim is to swap the focused client with the first minimized client, but not a simple cycle as I want it to be agnostic to how many un-minimized clients there are on screen. It works as intended, except that the positioning of the client on the screen isn't preserved. From what I can tell, if the newly un-minimized & focused client has a higer index than the next highest un-minimized client, then it will always end up positioned after it on the screen, and I have no idea how to get around this.
While it does nothing to clarify the issue I was running into, here's the workaround I came up with to accomplish the goal I had in mind: if client.focus then local c = client.focus local nxt = nil for x in awful.client.iterate(function(x) return x.minimized end) do if nxt then nxt:swap(x) else nxt = x end end c.minimized = true nxt.minimized = false c:swap(nxt) client.focus = nxt end I decided to do away with keeping the clients in their original order, and instead, any x of un-minimized clients will occupy positions 1-x in the clients table, while any minimized clients will form a queue along the remaining positions. Conveniently, spawning a new client gives it focus, makes it a master, and puts it in the first position, so the ordering is maintained. It works ¯\_(ツ)_/¯
Trouble with "string.contains" function
I am writing a web form that has a unique travelID per travel request. (see blank column in picture below, I'm not high enough reputation to embed the picture in here) Some of the travel requests have attached documents and others do not. I wrote this code: Dim dirs As String() = Directory.GetFiles("E:\DomainWebs\Intranet\fileups\TravelDocs\") Dim i As Integer = 0 For Each GridRecord As GridRecord In TravelWebDataGrid.Rows For Each doc As String In dirs If doc.Contains(TravelWebDataGrid.Rows(i).Items(10).Value) = True Then TravelWebDataGrid.Rows(i).Items(11).Value = True End If Next i += 1 Next Just for testing, only the top Travel Request has documents attached. As you can see, it is checking the second row checkbox as well even though it doesn't have any documents attached. This is what is being compared to row 2: "DocName" - E:\DomainWebs\Intranet\fileups\TravelDocs\RONNIEP20180124141116-Hello.docx "TravelID" - RONNIEP20180124135357 Does anyone know why it is doing this? Let me know if you need any more information. Thanks in advance for your responses.
This might be off because I haven't worked with a datagrid but it looks like the code has been over-complicated with the counter. Can you do this? ' you're looping gridrecords/rows. For Each GridRecord As GridRecord In TravelWebDataGrid.Rows For Each doc As String In dirs ' use the gridrecord here, not rows(i). If doc.Contains(GridRecord.Items(10).Value) = True Then ' and here. GridRecord.Items(11).Value = True End If Next Next
How to use recursive function in Lua to dynamically build a table without overwriting it each call
I have a need to crawl a set of data of indeterminate size and build a table key/value index of it. Since I don't know the dimensions in advance, seems I have to use a recursive function. My Lua skills are very new and superficial. I'm having difficulty understanding how to deal with returning a table from the function call. Note this is for a Lua 5.1 script processor API = function(tbl) local table_api = {} -- do stuff here with target data and add to table_api table_api["key"] = value -- then later there is a need to recurse deeper into target data table_api["lower"] = API(var) return table_api end result = API(source_data) In most every other language I know there would be some way to make the recurse line table_api["lower"] = API(var) work but since Lua does table variables by reference, my return sub-table just keeps getting overwritten and my result is a tiny last bit of what it should be. Just for background on my purpose: there's a commercial application I'm working with that has a weakly documented Lua scripting interface. It's running Lua 5.1 and the API is not well documented and frequently updated. As I understand it, everything is stored in _G, so I wanted to write something to reverse engineer the API. I have a working recursive function (not shown here) that enumerates all of _G. For that return value, it just builds up an annotated string and progressively builds on the string. That all works fine and is really useful, but it shows much more that the API interface; all the actual data elements are included, so I have to sift through like 30,000 records to determine an API set of about 500 terms. In order to determine the API, I am trying to use this sub-table return value recursive function being discussed in this question. The code I'm showing here is just a small distilled subset of the larger function. I'll go ahead and include the full code here. I was hoping to incrementally build a large'ish table of each API level, any sublevels, and finally whatever keys used at the lowest level. In the end, I was expecting to have a table that I could address like this: result["api"]["label"]["api"]["sublabel"]["value"]["valuename"] Full code: tableAPIShow = function(tbl, table_track) table_track = table_track or {} local table_api = {} if type(tbl) == 'table' then -- Check if values are tables. local parent_table_flag = true for ind,val in pairs(tbl) do if type(val) ~= 'table' then parent_table_flag = false break end end -- If all children are table type, check each of them for subordinate commonality local api_flag = false if parent_table_flag == true then local child_table = {} local child_table_flag = false api_flag = true for ind,val in pairs(tbl) do -- For each child table, store the names of the indexes. for sub_ind,sub_val in pairs(val) do if child_table_flag == false then -- First time though, create starting template view of typical child table. child_table[sub_ind] = true -- Store the indexes as a template table. elseif child_table[sub_ind] == nil then -- Otherwise, test this child table compared to the reference template. api_flag = false break end end if api_flag == false then -- need to break out of nested loop break end child_table_flag = true end end if api_flag == true then -- If everything gets to here, then this level is an API with matching child tables below. for ind,val in pairs(tbl) do if table_api["api"] == nil then table_api["api"] = {} end table_api["api"][ind] = tableAPIShow(val, table_track) end else -- This level is not an API level, determine how to process otherwise. for ind,val in pairs(tbl) do if type(val) == 'table' then if table_track[val] ~= nil then -- Have we already recursed this table? else table_track[val] = true if table_api["table"] == nil then table_api["table"] = {} end table_api["table"][ind] = tableAPIShow(val, table_track) end else -- The children are not tables, they are values if table_api["value"] == nil then table_api["value"] = {} end table_api["value"][ind] = val end end end else -- It's not a table, just return it. -- Probably never use this portion because it's caught on upper level recurse and not called return tbl end return table_api end And I was calling this function in the main script like this: local str = tableAPIShow(_G) I've got another function that recursively shows a table so I can look inside my results and see I only get a return value that contains only the values of the top-level of _G (I have it excluded built-in Lua functions/values because I'm only interested in the Application API): { [value] = table: 00000000F22CB700 { [value][_VERSION] = Application/5.8.1 (x86_64; Windows NT 10.0.16299), [value][tableAPIShow] = "function: 00000000F22C6DE0, defined in (121-231) C:\\Users\\user\\AppData\\Local\\Temp\\APP\\/~mis00002690 ", [value][_FINAL_VERSION] = true, [value][Path] = ./Scripts/Database/elements/, [value][class] = "function: 00000000F1953C40, defined in (68-81) Scripts/Common/Class.lua ", [value][db_path] = ./Scripts/Database/, [value][merge_all_units] = "function: 00000000F20D20C8, defined in (2242-2250) Scripts/Database/db_merge.lua ", }
You just need to localize the variable you store your table in and it will work as you expect: local table_api = {} (note that you are passing table variable that conflicts with the global table variable and is not currently used in the function.)
I am inclined to believe that your tableAPIShow function code is working correctly and the another function that recursively shows a table fails to serialize your table fully. Hence you don't see the deeper levels of the table returned by tableAPIShow(). I got your initial and current code (tableAPIShow) to work with my simple table serialize function: the whole _Global table is exported completely and formatted as you implemented it in your tableAPIShow(). Code for testing: apiMassiveTable = { api = { get = { profile = {"profileID", "format"}, name = {"profileID", "encoding"}, number = {"profileID", "binary"} }, set = { name = {"apikey", "profileID", "encoding", "newname"}, number = {"apikey", "profileID", "binary", "newnumber"} }, retrieve = {} }, metadata = {version="1.4.2", build="nightly"} } -- tableAPIShow implemenation here table.serialize = dofile("serialize.lua") print(table.serialize("myNameForAHugeTable", tableAPIShow(_G))) PS: Whatever serialize function you're using, it should enquote strings like Application/5.8.1 (x86_64; Windows NT 10.0.16299) which it does not.
Like #Paul Kulchenko said, you need to learn to use locals (https://www.lua.org/pil/4.2.html). Global variable post-exist until a new lua_State is loaded (a new environment, could be a new process depending on what interpreter you are using). So a tip is to always use local variables for anything you don't want to leave the function or leave the compilation unit. Think of tables like dictionaries: a word is attached to a definition. Thusly the definition is the data. What I think you are trying to do is serialization of a table of data. However, that isn't really necessary. You can either shadow copy or deep copy the given table. A shadow copy is when you don't delve into the depths of tables found in the keys, etc. A deep copy is when you copy tables in keys of tables in keys of tables... etc. local shallow_copy = function(tab) local rep_tab = {} for index, value in pairs(tab)do rep_tab[index] = value end return rep_tab end -- because local variable is not defined or declared immediately on a 1-liner, -- a declaration has to exist so that deep_copy can be used -- lets metatable execute functions local deep_copy deep_copy = function(tab) local rep_tab = {} for index, value in pairs(tab)do if(type(value) == "table")then rep_tab[index] = deep_copy(value) else rep_tab[index] = value end end return rep_tab end Deco's deepcopy.lua https://gist.github.com/Deco/3985043 You can also index tables using periods: local tab = {} tab.abc = 123 tab["def"] = 456 print(tab.abc, tab["def"]) To serialize the entire _G, you would just filter out the junk you don't need and recurse each table encountered. Watch out for _G, package, and _ENV because if defined it will recurse back to the start. -- use cap as a whitelist enumerate_dir = function(dir, cap) local base = {} for i, v in pairs(dir) do -- skip trouble if(i ~= "_G" and i ~= "_ENV" and i ~= "package")then if(type(v) == "table")then -- if we have a table base[i] = enumerate_dir(v, cap) else for k, n in pairs(cap) do if(type(v) == n)then -- if whitelisted base[i] = tostring(v) end end end end end return base end -- only functions and tables from _G please local enumeration = enumerate_dir(_G, {"function", "table"}) -- do some cool quips to get a basic tree system prefix = "" recursive_print = function(dir) for i, v in pairs(dir)do if(type(v) == "table")then print(prefix, i, v) prefix = prefix .. ">" recursive_print(v) else print(prefix, i, v) end end if(#prefix > 0)then prefix = prefix:sub(1, #prefix-1) end end recursive_print(test)
how to access string declared variables in scilab
I am having trouble with is line "P_dot_ij_om_+ii(i,1)=P_dot_ij(k,2);" basically I have declared matrix P_dot_ij_om_1=[] from 1 to i and in the next line. I would like to input data e.g. P_dot_ij_om_+ii(i,1)=P_dot_ij(k,2); where ii is a number. what is the right expression. rows=round(k/360); i=1; ii=1; k=1; while ii <= rows Pdot_names(ii,1)=string("P_dot_ij_om_"+ string(ii)); disp(Pdot_names(ii)) execstr(Pdot_names(ii)+'=[]'); // declare indexed matrix while i<361 P_dot_ij_om_+ii(i,1)=P_dot_ij(k,2); // P_dot_ij_om_+ii(i,2)=P_dot_ij(k,3); disp(k) k=k+1; i=i+1; end ii=ii+1; end
The code below works, but in general it is not advised to create string variables. There are much faster and also easier to implement alternatives, see e.g. this thread: How can I create variables Ai in loop in scilab, where i=1..10 rows = 2; P_dot_ij = [10,20,30;11,21,31;12,22,32]; i=1; ii=1; k=1; while ii <= rows //Pdot_names(ii,1)=string("P_dot_ij_om_"+ string(ii)); The firs 'string' is unnecessary Pdot_names(ii,1)="P_dot_ij_om_"+string(ii); disp(Pdot_names(ii)) execstr(Pdot_names(ii)+'=[]'); // declare indexed matrix while i<4 //P_dot_ij_om_+ii(i,1)=P_dot_ij(k,2); execstr("P_dot_ij_om_"+string(ii)+"("+string(i)+",1)=P_dot_ij("+string(k)+",2)"); // P_dot_ij_om_+ii(i,2)=P_dot_ij(k,3); execstr("P_dot_ij_om_"+string(ii)+"("+string(i)+",2)=P_dot_ij("+string(k)+",3)"); disp(k) k=k+1; i=i+1; end ii=ii+1; end disp(P_dot_ij_om_1,"P_dot_ij_om_1"); disp(P_dot_ij_om_1,"P_dot_ij_om_2"); And also next time please post selfcontained code examples, because otherwise I can only guess what is k and P_dot_ij.
Changing increment variables causes for loop to go over limit
In my loop I am trying to remove items from a list that have a certain name. I can't do this with a for-each, so I tried a regular for-loop. It seems the for loop is not working as expected. It always goes over the limit. I had to put an if-then to break out of the loop (very ugly solution). I'm trying to find the correct way to accomplish this. Dim canShowNextTable As Boolean = False Dim allTablesInTab As List(Of Control) = ctrlFinder.GetTypeOfControls("Table", parentForm.Controls) Dim totalTables As Integer = allTablesInTab.Count - 1 For i As Integer = 0 To totalTables If allTablesInTab.Item(i).ID = "CustomerTable" Or _ allTablesInTab.Item(i).ID = "PMTable" Or _ allTablesInTab.Item(i).ID = "TableAListClrnCheck" Or _ allTablesInTab.Item(i).ID = "TableBListClrnCheck" Or _ allTablesInTab.Item(i).ID = "TableCListClrnCheck" Or _ allTablesInTab.Item(i).ID = "TableDListClrnCheck" Or _ allTablesInTab.Item(i).ID = "TableSignature" Then '' If the ID is one of these remove it from list allTablesInTab.Remove(allTablesInTab.Item(i)) totalTables = totalTables - 1 '' Decrement number of tables to loop through i = -1 '' Reset counter to prevent going over or premature stopping End If If i = 3 AndAlso totalTables = 3 Then '' Since loop continuously goes over limit, use if-then to exit for-loop Exit For End If Next
You need to traverse your loop in reverse because once you remove an item the total count has changed and is no longer correct. Looping in reverse avoids this issue. For i As Integer = totalTables To 0 Step -1 Also, instead of allTablesInTab.Remove(allTablesInTab.Item(i)) you can use: allTablesInTab.RemoveAt(i) Work through this logic on paper or the debugger to properly grasp the concept of what's happening. You might also find this related question useful. It's in C# but the concepts are the same: How to remove elements from a generic list while iterating around it?