Linked Lists
BlitzMax Forums/BlitzMax Beginners Area/Linked Lists
| ||
Hi, Have a list of objects (many 1000's) and I go through the list with the EachIn method. I want to use Function RemoveLink( link:TLink ) to remove some of them during the pass. How do I use this command? I've to pass it a TLink but all I have is a TList Jim |
| ||
Hi You can do this: local temp:Tobject local i% = 0 For local ob:Object = EachIn List if (some_condition) temp = List.ValueAtIndex(i) List.Remove(temp) exit 'get out from loop endif i = i + 1 Next |
| ||
MyList.Remove object if you want to avoid having to use :TLink You can safely use this in an Eachin loop Example: Framework brl.standardio Import brl.linkedlist Strict Global MyList:TList = New TList MyList.AddLast "Pear" MyList.AddLast "Apple" MyList.AddLast "Banana" MyList.AddLast "Peach" MyList.AddLast "Lemon" MyList.AddLast "Strawberry" Print "--LIST--" For Local name$ = EachIn MyList If name.StartsWith("P") MyList.Remove name Continue EndIf Print name Next End A version with :TLink Framework brl.standardio Import brl.linkedlist Global list:TList=New TList Global link:TLink list.addlast "I" list.addlast "have" list.addlast "eaten" list.addlast "a frog!" link=list.FirstLink() While link<>Null Local t$=String(link.Value()) If t$="eaten" link.Remove link=link.NextLink() Wend For Local name$=EachIn list Print name Next |
| ||
Thanks Guys, very helpfull. I'm basically looking for speed and I'm right in thinking that doing the link.remove is the fastest way? Thanks again Jim |
| ||
I'm finding this linked list of objects, using TLink is as fast as an array of objects using TLink. Very happy! |
| ||
Yes JBR, link.remove will be faster. You will need to store the relevant link as a field in your objects to get the benefit of this speed if you are removing objects in a 'random' fashion. |
| ||
Thanks |
| ||
Look at my post here http://blitzbasic.com/Community/posts.php?topic=91355 |
| ||
Follow on question. When I remove a link, I want to add 3 more objects to the list.Framework brl.standardio Import brl.linkedlist Global list:TList=New TList Global link:TLink list.addlast "I" list.addlast "have" list.addlast "eaten" list.addlast "a frog!" list.addlast "YUMMY!" link=list.FirstLink() While link<>Null Local t$=String(link.Value()) If t$="eaten" Then link.Remove list.addlast "abc" list.addlast "abc" list.addlast "abc" EndIf link=link.NextLink() Wend For Local name$=EachIn list Print name Next It seems to work, but not sure if I'm being lucky! Is this ok to do? Jim |
| ||
We posted at the same time! Unless I'm mistaken, you are being lucky. Addlast puts it on the end of the list, regardless where your current link was. Try looking up the TLink/TList methods, there might be something such as "insert after link" that you can try. Then remove the link. Your code gives me this output: I have a frog! YUMMY! abc abc abc |
| ||
Hi Czar, that is the output I get & want. Just the adding to the end of the list. Having a look at your link. Jim |
| ||
Ok I thought you meant you wanted abc after eaten and before a frog. :) |
| ||
One small tip, if the order is not important, adding an object to the top of the list is supposed to be a bit quicker:list.AddFirst "Put me on top" To wrap things up, here is a demo which I put together a long time back, which features everything to do with adding, removing, editing, and inserting items (before and after) into a list: |
| ||
One small tip, if the order is not important, adding an object to the top of the list is supposed to be a bit quicker What makes you think that? BRL's linked list is actually a circular doubly-linked list (in which each link has a reference to its neighbors, and a root link links the first and last links), so that to get the last link you simply need to get the preceding link on the head link (which also has the first link as the next link). |
| ||
I try to stick with adding to the top of the list in speed critical situations not because it matters in bmax (as mentioned by plash it's doubly linked and circular so it doesn't matter), but because if/when I want to port that code to something else that doesn't have quick access to the end of the list I won't have to re-think for performance... but I also refuse to code bmax in anything but superstrict, and I use a lot of languages regularly, so maybe that's just me being anal :0) |
| ||
Hi again,While link<>Null Local t$=String(link.Value()) If t$="eaten" link.Remove link=link.NextLink() Wend I've got my particles working using Jim Brown's code. But I'm curious about a few things. 1) How does it work that you link.Remove and then you link.NextLink(). Surely link is gone after the link.Remove? 2) I have a list of objects, jim:MyType = MyType(link.Value()) and after link.Remove I find I can still access the jim fields at the removed link. I guess what I'm trying to say is how does everything work after the link.Remove command? Jim |
| ||
Every object in a Tlink has a reference to the previous object and the next object. When an object is removed from the link chain, the reference from the previous object is change to the next object and the referece from the next object is changed to the previous object skipping the current object all together. the reason you can still access the previous object and the next object from the "current object" is because the reference to the next and previous objects are left in it. The reason that the object can be collected by the garbage collector is because now there is no reference to it any more but sense the current object still has reference to the previous and and next object you can still access the objects in the link chain. I hope this is clear. if you have time look at the source code for Tlink. It might be easier to understand. |
| ||
Thanks Jesse, I think I understand ... used with B3D doing it all for me. Garbage collection is 'new' aswell ... if there is a reference to an object then the object is safe. Thanks Jim |
| ||
Is it OK for me to add a new question here about TLists? Can I change the members of a list in place? Or do I need to put them in a new list one by one, changing them as I go, and then replace the old list with the new list? |
| ||
I don' know what you mean by number. objects in a list are not numbered unless you use a field to assign them numbers which in case you would have to number each object. |
| ||
Can I change the members of a list in place? Or do I need to put them in a new list one by one, changing them as I go, and then replace the old list with the new list? You need to put them in a new list. Removing and inserting things from/into a TList while you iterate through it (with EachIn) is a recipe for breaking the TList. If you're not using the iterator, then it's probably fine. |
| ||
You can use a TLink to manually navigate through a list when you need something a bit out of the ordinary. Look up TLink in the docs. |