| 05-10-2006, 06:30 PM | #1 |
Hmm, is there a function for getting the index of a certain value within an array? Example: local string array blah blah[1] = "OK" Now i have the "OK" and want to retrieve the index (1) of blah... GetIndexOfValue(OK, blah)?? >_< |
| 05-10-2006, 06:33 PM | #2 |
Old school loop until you find it. Alternatively you can use game cache which is actually a great alternative for this case JASS:call StoreInteger(gc,"blah","OK",1) |
| 05-10-2006, 09:21 PM | #3 |
Just search through the array with a loop. Like this: JASS:local integer i = 0 local integer index = -1 loop if str == blah[i] then set index = i endif exitwhen i > 1000 or not(index = -1) set i = i + 1 endloop |
| 05-10-2006, 10:20 PM | #4 | |
Quote:
Hmm, i was thinking that looping might be too slow... Anyway, this gamecache thing looks interesting, could you explain that a bit more? |
| 05-11-2006, 01:53 AM | #5 |
Looping is not too slow. Not even close. In my map I have a 'translator' system set up, where it will automatically translate names like "custom_n00A" to "weaponshop" and back; this loops through a large translation table anytime anything gets messaged or any chat command is entered. I also catch *all* chat messages and do string matches on them manually. The map checks each chat message for several hundred commands, because I provide a huge amount of redundency. It's full of chunks like this: JASS:elseif (str == "gate") then call SelectUnitForPlayerSingle( GUI_D_P_Gate, pl ) elseif (str == "elvengate") then call SelectUnitForPlayerSingle( GUI_D_P_ElvenGate, pl ) elseif (str == "elven gate") then call SelectUnitForPlayerSingle( GUI_D_P_ElvenGate, pl ) elseif (str == "demonicgate") then call SelectUnitForPlayerSingle( GUI_D_P_DemonicGate, pl ) elseif (str == "demonic gate") then call SelectUnitForPlayerSingle( GUI_D_P_DemonicGate, pl ) elseif (str == "demongate") then call SelectUnitForPlayerSingle( GUI_D_P_DemonicGate, pl ) elseif (str == "demon gate") then call SelectUnitForPlayerSingle( GUI_D_P_DemonicGate, pl ) elseif (str == "wall") then call SelectUnitForPlayerSingle( GUI_D_P_StoneWall, pl ) elseif (str == "stonewall") then call SelectUnitForPlayerSingle( GUI_D_P_StoneWall, pl ) elseif (str == "stone wall") then call SelectUnitForPlayerSingle( GUI_D_P_StoneWall, pl ) elseif (str == "line") then call SelectUnitForPlayerSingle( GUI_D_P_Line1, pl ) elseif (str == "wallline") then call SelectUnitForPlayerSingle( GUI_D_P_Line1, pl ) elseif (str == "wall line") then call SelectUnitForPlayerSingle( GUI_D_P_Line1, pl ) My map does a completely absurd amount of string matching, and there is no slowdown whatsoever. Don't worry, you're golden. |
| 05-11-2006, 01:28 PM | #6 |
Looping is terribly slow. Fact is that in this case gamecache is much better. Code will be easier to write and everything will be faster The hard thing is to have a global gamecache variable that is initialized before every other line uses it. Let's name it gc JASS:function gcthing takes nothing returns gamecache if (udg_gc==null) then // senseless, but necessary: call FlushGameCache(InitGameCache("goo.dat")) set udg_gc=InitGameCache("goo.dat") endif return udg_gc endfunction That is a function in the custom script section so every trigger can use it if it wants. store:local gamecache gc=gcthing() call StoreInteger(gc,"fruits","Orange",1) call StoreInteger(gc,"fruits","Apple",2) // call StoreInteger(gc,"fruits","Lemon",1345) set gc=null get:function GetFruitNumber takes string s returns integer if ((s=="") or (s==null)) then return 0 endif return GetStoredInteger(gcthing(),"fruits",s) endfunction |
| 05-12-2006, 01:09 AM | #7 |
A linear loop may be bad on a large number of strings in a language like java, but to war3 they're pretty much equivoical as a number of ints. If the number is small like say 10 ints it shouldn't be a problem. equivalence tests on strings take the same time on ints as strings (with good reason). The only problem is you can't do a binary search on strings since string content comparisons in jass are even worse then in java. The "speedup" for log(n) search time might will be killed by the linear test time for small arrays. Remember, that = is constant but LexicallyGreater or whatever is not. If you have a huge number of strings then it might be worth it. |
| 05-12-2006, 07:03 AM | #8 |
That gamecache thing amazes me to no end....just a few more questions: JASS:call StoreInteger(gc,"fruits","Orange",1) Like, i could get the stored Integer like this JASS:call GetStoredInteger(gcthing(), s ,"Orange") Edited by Blade.dk. Reason: Replaced code tags with jass tags. |
| 05-12-2006, 07:12 AM | #9 |
Yup! Hash tables are fantastic! And if you reserve one character for a delimiter (or if you're really clever you can do with out), you can make your arrays infinite dimensional. Also, note that capitalization is ignored by the hash algorithm: "Orange" and "orange" will access the same string. |
| 05-12-2006, 08:31 AM | #10 | ||
Quote:
Exactly. For something like this, it's perfect; looking up the index in a String array is no different than any other object, because it's all just pointers. An integer comparison is dirt cheap, even in Warcraft. This is how my own map runs seamlessly even with an absurd number of String comparisons. Quote:
Nope. Anitarf measured the speed of using global arrays as 4 times faster than using a Gamecache. Or did I misunderstand this post? http://wc3campaigns.net/showpost.php...9&postcount=22 Anyway the point he's making, and that I agree with, is that neither one makes any significant difference, so use whichever you want. I prefer looping for this sort of index-finding; I just find it simpler and cleaner than using a Gamecache. Personal preference I guess. |
| 05-12-2006, 09:01 AM | #11 |
You gave an example with 1000 elements! did you mean game cache is 250x faster? OK, exaggeration. Whatever works for you, but game cache, besides being morally correct performance wise ;), 1) naturally packages a clean interface 2) dynamic allocation 3) passing! None of your treasured abstract interface with arrays... |
| 05-12-2006, 10:16 AM | #12 |
How is loop-comparing over 50 indexed arrays 10 times faster than to "pick" out a stored data from a gamecache? I doubt it's even cleaner, wait, it is definitely not cleaner... Or are you saying that JASS:if OK == 1 then set blah = 1 elseif OK == 2 then set blah = 2 elseif OK == 3 then set blah = 3 ... elseif OK == 50 then set blah = 50 JASS:local string(does integer work too?) i set bla = GetStoredInteger(gc, "OK", i) Edited by Blade.dk. Reason: Replaced code tags with jass tags. EDIT: ... I just read somewhere that this gamecache thing is only used for singleplayer? -_-;; I have been wondering that this Code:
native InitGameCache string campaignFile Where and how is this campaign file supposed to be? Can i import it into the map? |
