Remove a single instance from a List
Monkey Forums/Monkey Programming/Remove a single instance from a List
| ||
I have a List called Inventory that is made up of Item Objects. When an Item is added to the List I just do Inventory.AddLast(Item), but when I try to remove an Item, it removes all instances of that Item instead of just 1.Global ItemList:List<Item> = New List<Item> Global Inventory:List<Item> = New List<Item> Class Item Field Description:String Field Value:int Function Create:Void(description:String,value:int) For Local Item:Item = New item Item.Description = description Item.Value = value ItemList.Addlast(Item) End Function End Class 'Create Some Items Item.Create("Hat",10) Item.Create("Pants",20) Item.Create("Shoes",30) 'Add 2 of each Item to the Inventory List For Local Item:Item = Eachin ItemList Inventory.AddLast(Item) Inventory.AddLast(Item) Next Local Item:Item = Inventory.First() Inventory.Remove(Item) Inventory.Remove(Item) takes out Both of the Hat entries instead of just 1. Is there a way to only remove the first instance of 'Hat" in the list? |
| ||
couldnt you do:Local Count =0 For Local Item:Item = Eachin ItemList if Count =0 Inventory.Remove( Item ) Count += 1 Next This way it will remove the first one from the list and leave the rest intact? |
| ||
can you please try posting some executable code next time as there are a bunch of syntax errors in your code that would defer others from helping you. Welcome to the forums :). there is something very wrong with this lines: Inventory.AddLast(Item) Inventory.AddLast(Item) I would advice you agains doing that as the list only stores addresses of objects so in your case the list will store the same object address in two different locations in the list. this means that if you modify one item in the list it will modify both since they are both the same object. that goes similar for the removal of the objects. The list uses this function for removing objects from the list: Method RemoveEach( value:T ) Local node:=_head._succ While node<>_head Local succ:=node._succ If Equals( node._data,value ) node.Remove node=succ Wend End if you notice you will see that the while loop will continue until it's done comparing all of the objects. so if the same object address is in the list more than once, it will remove all of the instances of the same object. and that's why you see that it removes two objects in your case. |
| ||
Thanks for the quick and thorough response Jesse! Sorry about that. Here is something that will actually run.Global ItemList:List<Item> = New List<Item> Global Inventory:List<Item> = New List<Item> Class Item Field Description:String Field Value:Int Function Create:Void(description:String,value:Int) Local Item:Item = New Item Item.Description = description Item.Value = value ItemList.AddLast(Item) End Function End Class Function Main:Int() 'Create Items Item.Create("Hat",10) Item.Create("Shirt",20) Item.Create("Pants",30) 'Add 2 of each object into the Inventory For Local Item:Item = Eachin ItemList Inventory.AddLast(Item) Inventory.AddLast(Item) Next 'Find the 1st Hat by value and remove it For Local Item:Item = Eachin ItemList If Item.Value = 10 Then Inventory.Remove(Item) Exit End If Next 'Print the remaining Items in Iventory For Local Item:Item = Eachin Inventory Print Item.Description Next Return 0 End Function What you said makes perfect sense. Now I understand why the Remove() is getting rid of more than I intended. That being said, what is a correct way to approach this? How can I make an Inventory list of Item objects that can be added to and removed from? |
| ||
Treat the objects as in real life(figuratively), "instantiate" as many objects of the same class as you think you will need in the itemlist. It all depends on the type of game you are making that will determine how you will be able to store the objects. it might help if you mention what type of game you are working on. |
| ||
It is for an RPG style inventory. The player will be able to buy and sell items so the content of the inventory will constantly be changing. If there are for instance, 50 different possible items the player can have, then the inventory must be able to hold any amount (to a limit) and combination of the those 50 items. I suppose an Array would be an easy way to do it, but lists seemed so much more logical. |
| ||
a list would be fine. just instantiate each instance of the object with new. |
| ||
At what point in the above code would New need to be used? When it is added to the Inventory List? |
| ||
They way you remove the item is a slower method than using the node you get when you add it. Try this: [monkeycode] Global ItemList:List<Item> = New List<Item> Global Inventory:List<Item> = New List<Item> Class Item Field Description:String Field Value:Int Field listNode:list.Node<Item> = Null Function Create:Void(description:String,value:Int) Local Item:Item = New Item Item.Description = description Item.Value = value Item.listNode = ItemList.AddLast(Item) End Function Method Remove:Void() Self.listNode.Remove() End End Class Function Main:Int() 'Create Items Item.Create("Hat",10) Item.Create("Shirt",20) Item.Create("Pants",30) 'Add 2 of each object into the Inventory For Local Item:Item = Eachin ItemList Inventory.AddLast(Item) Inventory.AddLast(Item) Next 'Find the 1st Hat by value and remove it 'Iterate through the list backwards when you want to remove several items. For Local Item:Item = Eachin ItemList.Backwards If Item.Value = 10 Then Item.Remove() Exit End If Next 'Print the remaining Items in Iventory For Local Item:Item = Eachin Inventory Print Item.Description Next Return 0 End Function [/monkeycode] |
| ||
@Bob I think what you really need is an item manager. the item manager is what will hold all of the items for the game. its like a pool that you can store all of the objects into and remove them at will. then add them to the inventory list as needed. you can create the item manager with a list as a field. you would have to fill the whole list by creating instances of as many objects as needed for the game. example: itemList.AddLast(new Item("hat",30)) itemList.AddLast(new Item("hat",30)) itemList.AddLast(new Item("hat",20)) itemList.AddLast(new Item("Pant",30)) itemList.AddLast(new Item("Shirt",10)) Class Item Field Description:String Field Value:Int Method New(description:String,value:Int) Self.Description = description Self.Value = value End Method End Class |
| ||
Thanks for the help guys! I'll give these methods a shot and see if they work for what I need. I appreciate the guidance! |