killjoy37
|
  |
| Joined: 27 Aug 2008 |
| Total Posts: 2821 |
|
|
| 11 May 2013 10:13 AM |
I have a table that I am constantly traversing, with each index taking one second long before going to the next. When I have reached the end of the table, I have to start back at the beginning. This is not much of a problem. However, while I am iterating through the table, some values may be added to it or removed from it. When a value is added a part of the table I haven't got to yet in the loop, there is no problem, but when a value is added to a part of the table that the loop has already passed, I need to be able to go to it immediately, and then pick up where I left off, OR, if another value was added yet again behind the stopping place, then I need to go to it. |
|
|
| Report Abuse |
|
|
jobro13
|
  |
| Joined: 05 Aug 2009 |
| Total Posts: 2865 |
|
|
| 11 May 2013 10:16 AM |
| Metatables. The __newindex field provides exactly what you need; it gives the index it wants to get set and the value where it has to be set to. You can then go back to that index and continue to what you were doing. |
|
|
| Report Abuse |
|
|
killjoy37
|
  |
| Joined: 27 Aug 2008 |
| Total Posts: 2821 |
|
|
| 11 May 2013 10:57 AM |
| Thank you, I'll look into that. |
|
|
| Report Abuse |
|
|
killjoy37
|
  |
| Joined: 27 Aug 2008 |
| Total Posts: 2821 |
|
|
| 12 May 2013 11:00 AM |
@Jobro13
About the code you gave me in the message:
local tab = {} -- The table with the stuff in it. local metatable = {} -- the table where we put the metamethods in. local linkedtab = {} metatable.__index = function(tab, ind) return linkedtab[ind] end -- returns the index in the linked table. metatable.__newindex = function(tab, ind, val) process(ind, val) linkedtab[ind] = val end setmetatable(tab, metatable)
You said that "tab" was always empty, but I don't understand why, so I'm going to try to explain my problem with the code I created instead so we can be on the same page. It's probably very inefficient, but it looks like it will work. (I can't test it yet).
The actual code is about 80 lines, but I'm omitting some that I know are fine.
isNecessary = false place = 0 iterator = 1 tower = script.Parent meta = { __newindex = function(tab,ind,val) if val:FindFirstChild("Checker") or tower.Current.Value == val or ind <= iterator then isNecessary = true end rawset(tab,ind,val) end } enemies = setmetatable({},meta)
while #enemies > 0 do if isNecessary then tower.Target.Value = enemies[place+1].Value isNecessary = false else tower.Target.Value = enemies[iterator].Value end wait(1) iterator = (iterator + 1)%(#enemies) end
tower.PotentialTargets.ChildAdded:connect(function(alien) place = 0 if #enemies > 0 then --rest of my 80 lines table.insert(enemies,place+1,nil) enemies[place+1] = alien else enemies[1] = alien end end)
So, what happens first is an objectvalue is added to a model called "PotentialTargets" and on the ChildAdded event, I add it to the table "enemies" If #enemies == 0 then I just put it in the first spot and I'm done, but otherwise I have to figure out where to place it in the table, and that is the part I left out. Then you can see I use table.insert(enemies,place+1,nil). I did this because I can't simply replace a value with alien, I need to make room for it, and I made it nil so that when I attempted to put alien in that same spot in the next line - enemies[place+1] = alien - it would still trigger the newindex metamethod. Don't worry about place+1.
When it goes to the newindex metamethod, you can see it goes through an if statement.
if val:FindFirstChild("Checker") or tower.Current.Value == val or ind <= iterator then
These are the conditions where I would want it to immediately "process()" alien. My process() function is just the while loop below the metatable.
Anyway.. If it means one of those conditions, it sets a value isNecessary to true, meaning it is necessary to stop the loop for a moment, "process()" alien, and then go back to the loop. It is important that I go back to the place I stopped in the loop, which is why I have an iterator variable, which tells me where I am in the loop.
I notice that I'm jumping around a lot so I'll finish talking about the metatable, and then start talking about my while loop.
At the end of the metamethod is rawset, where I actually place alien in the table. In the while loop, I immediately check to see if isNecessary is true, and if it is, then I apply the effects to enemies[place+1] which is where I just placed the alien. Otherwise I just apply the effects to the next value in the table. Then I added 1 to the iterator variable in either case of isNecessary and take the modulus of iterator and #enemies so I can start over. I'm aware that it won't work right at the moment but I'm not worried about the modulus part.
Thanks |
|
|
| Report Abuse |
|
|
jobro13
|
  |
| Joined: 05 Aug 2009 |
| Total Posts: 2865 |
|
|
| 19 May 2013 06:05 AM |
What I would do is to use table.remove. If you use table.remove it automatically fills gaps. Example:
t = {3,4,5} table.remove(t,2) print(t[1], t[2]) -- > 3,5
If you use table.insert(t,val) then it will always be put on the end of the table.
In this case, I don't think you need metatables, as on the point you insert the value, you can immediately process() it? |
|
|
| Report Abuse |
|
|
killjoy37
|
  |
| Joined: 27 Aug 2008 |
| Total Posts: 2821 |
|
|
| 19 May 2013 09:31 AM |
This is the only case where it would be immediately processed:
if val:FindFirstChild("Checker") or tower.Current.Value == val or ind <= iterator then
and I used table.insert to make a space where I wanted to insert alien, because I had to push every other value up one. I made it nil because when I actually attempt to set the value of the index I just opened up, it will trigger the metamethod. With table.insert you can specify where you are inserting the value, by default it is at the end, but I find the correct spot to insert it in code that I didn't show you, open that spot up, then set it.
In the above conditional, I say 'if ind <= iterator then' with this I am just trying to see if placing the alien in the table would place it at a place the loop has already gone through this time around or not, and if it has already been passed up, I go back and process() it. |
|
|
| Report Abuse |
|
|
jobro13
|
  |
| Joined: 05 Aug 2009 |
| Total Posts: 2865 |
|
|
| 19 May 2013 09:57 AM |
| So, what exactly isn't working right now? |
|
|
| Report Abuse |
|
|
killjoy37
|
  |
| Joined: 27 Aug 2008 |
| Total Posts: 2821 |
|
|
| 19 May 2013 10:30 AM |
| Well, I can't test it yet, but really I was just wondering if the way I was doing it was efficient. Like, if there would be a different way to achieve the same effect, but quicker. |
|
|
| Report Abuse |
|
|