Click here to Skip to main content
15,885,777 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm trying to reduce a List during looping through it without success. From other posts I realise that this isn't possible as it causes an exception to be thrown. I cant seem to get other solutions offered working for my situation.

I cant run backwards as the data is order sensitive.

I think (from reading other solutions) that using a for i = 0 to might work instead of For Each XData as RangePoints, but I'm unsure how to do this as I can't also figure out to retain the ability to get access to the properties of XData used inside the loop in question.

As I'm inside a second loop will this cause difficulties?

....been struggling with this all day... it's driving me crazy so any help appreciated.

VB
For Each TData As RangePoints In DataList

    For Each XData As RangePoints In RemainingXPoints.Skip(1)
        XTRange = XData.Range - TData.Range
        myAngle = If(XTRange < Thresh, NearAngle, FarAngle)
        Dim Tj = New Double() {TData.Tx, TData.Ty, TData.Tz}
        Dim Bj = New Double() {TData.Bx, TData.By, TData.Bz}
        Dim Xk = New Double() {XData.Tx, XData.Ty, XData.Tz}
        If isLyingInCone(Xk, Tj, Bj, myAngle) = True Then
            ShadowList1.Add(CInt(XData.Tx) & "," & CInt(XData.Ty) & "," & CInt(XData.Tz))
        Else
            'Redefine RemainingXPoints to reduce it somehow?
        End If
    Next XData 'K

Next TData
Posted

You should collect all the items you want to remove from list1 into another list e.g called toBeRemoved. Then you can iterate over toBeRemoved and remove each item from list1. toBeRemoved should be local and will vanish as soon as it loses scope.
 
Share this answer
 
Comments
SheepRustler 25-Oct-15 12:22pm    
Hello bjoho,
I think I tried this with the code below, but I still get an exception. Maybe because I'm in a loop in a loop...?
Or have I misinterpreted your suggestion?

For Each TData As RangePoints In DataList
For Each XData As RangePoints In RemainingXPoints.Skip(1)
XTRange = XData.Range - TData.Range
myAngle = If(XTRange < Thresh, NearAngle, FarAngle)
Dim Tj = New Double() {TData.Tx, TData.Ty, TData.Tz}
Dim Bj = New Double() {TData.Bx, TData.By, TData.Bz}
Dim Xk = New Double() {XData.Tx, XData.Ty, XData.Tz}
If isLyingInCone(Xk, Tj, Bj, myAngle) = True Then
ShadowList1.Add(CInt(XData.Tx) & "," & CInt(XData.Ty) & "," & CInt(XData.Tz))
Else
NotShadowedYet.Add(XData) 'Collect Remaining Points?
End If
Next XData 'K
RemainingXPoints = NotShadowedYet
Next TData
bjoho 25-Oct-15 12:44pm    
I think it is that RemainingXPoints and NotShadowedYet is the same reference (object) and the statement "NotShadowedYet.Add(XData)" in the inner loop therefore changes the collection that controls the inner loop.
SheepRustler 25-Oct-15 13:40pm    
Yes, I guess so as the exception thrown is the same even though RemainingXPoints = NotShadowedYet is outside the inner RemainingXPoints loop..... must be something to do with having two loops, so I'm no nearer.
bjoho 25-Oct-15 14:35pm    
Think of it like this; At the outset you have all points in one collection NotShadowed, WHILE there are still some points in that collection (the outer loop) iterate over those and find the ones (toBeRemoved) that are now shadowed under a new angle. Outside (after) the inner loop, remove the new shadowed points from the NotShadowed collection. This goes on WHILE there are still some points left in NotShadowed. BREAK the outer loop on some criteria if you want.
SheepRustler 25-Oct-15 15:16pm    
Thanks bjoho,
I got the hint I think! :) I'll experiment for a WHILE....
MeanWHILE I think I found a LINQ solution that seems to work below:

Thanks for your help, its very much appreciated !

Dim ToDeleteList As New List(Of RangePoints)

For Each TData As RangePoints In DataList
For Each XData As RangePoints In RemainingXPoints.Skip(1).ToList
XTRange = XData.Range - TData.Range
myAngle = If(XTRange < Thresh, NearAngle, FarAngle)
Dim Tj = New Double() {TData.Tx, TData.Ty, TData.Tz}
Dim Bj = New Double() {TData.Bx, TData.By, TData.Bz}
Dim Xk = New Double() {XData.Tx, XData.Ty, XData.Tz}
If isLyingInCone(Xk, Tj, Bj, myAngle) = True Then
ShadowList1.Add(CInt(XData.Tx) & "," & CInt(XData.Ty) & "," & CInt(XData.Tz))
ToDeleteList.Add(XData)
End If
Next XData
RemainingXPoints = RemainingXPoints.Except(ToDeleteList).ToList
Next TData
I'd try storing the indices of the items to be removed in a Stack. Then Pop each index off the Stack and remove that item from the List.
 
Share this answer
 
v2
Comments
SheepRustler 25-Oct-15 13:35pm    
OK, A Stack. New to me but looks straightforward. But isnt the problem the same when then removing that item from the list - just modifying the list again?
PIEBALDconsult 25-Oct-15 15:20pm    
No. As with the other solutions, you remove the items after the foreach completes.
I guess that this is a follow up from previous question.
Your code is not complete since we don't know what is RemainingXPoints.
I will assume that all points are in DataList
Here is a piece of code that check if a point is in cone and gives you the list of points not in cone.
VB
Points= 0
For Scan= 1 to DataList.GetUpperBound(0)
    Visible= True
    For Check= 0 To Points
        XTRange = DataList(Check).Range - DataList(Scan).Range
        myAngle = If(XTRange < Thresh, NearAngle, FarAngle)
        Dim Tj = New Double() {DataList(Scan).Tx, DataList(Scan).Ty, DataList(Scan).Tz}
        Dim Bj = New Double() {DataList(Scan).Bx, DataList(Scan).By, DataList(Scan).Bz}
        Dim Xk = New Double() {DataList(Check).Tx, DataList(Check).Ty, DataList(Check).Tz}
        If isLyingInCone(Xk, Tj, Bj, myAngle) = True Then
            Visible= False
            Exit for
        End If
    Next
    If Visible Then
        Points= Points + 1
        DataList(Points) = DataList(Scan)
    End If
Next scan
' all valid points are between 0 and Points
For Scan= 0 to Points
Next Scan

The code is untested
 
Share this answer
 
v2
Comments
SheepRustler 26-Oct-15 9:30am    
Hello ppolymorphe & thanks for your post,
Yes this is a follow up. To reduce the time taken I've now split up my data into 4 data sets (one for each 2D quadrant) and run each one a separate BackgroundWorker. This has speeded things up dramatically but more importantly reduced the memory consumption as the number of comparisons is much less.
I'm currently 12 hours into a run through a 1.3 million point data set on my PC so I can't test your code on some real data, but I will do as soon as its finished and I've cooked my breakfast on the processor...........
Your help is appreciated.
Patrice T 26-Oct-15 10:33am    
I think more dramatic improvements are possible, but I think the whole proces must be reviewed.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900