Xilandro Posted July 11, 2014 Posted July 11, 2014 I have a serious problem with my arrays, and I'm in deep frustration, bc I have no idea how I can fix it. I have 2 arrays, array1 full of base objects, array2 full of values (condition, I can gather those values only once with Inventory references ForEach). Those values are at the same keys as base objects in array1. It looks like this: And I'm happy with it basically, until I try to sort arrays. If I will sort array1 by name - I want array2 elements get sorted as well. So, if 9mm Pistol in array1 at key [3.00] after sorting (into array3) is at key [12.0] - I want array2 element at key [3.00] be at key [12.0] (in array4) So I will have nice alphabetically sorted array3 with base objects and I will be able to access their values at same keys in array4. Thought about using stringmap, but keys with the same name will not work. Right now I'm thinking about to keep all the info in one array like "[0.00] 9mm Pistol___0.3", sort it, and then loop through that array and sv_split each element into new array and ar_append new elements into 2 new arrays.. something like that, clearly have no idea if this thing will work at all. update. This thing worked fine foreach loop let SomeString := $Iter + "___" + $Condition ar_append array1 $SomeString if nuked == 1 let ArraySorted := ar_sortalpha array1 let iSize := ar_size ArraySorted set nuked to 2 endif if nuked == 2 if iSize != 0 let array2 := sv_split $ArraySorted[0] "___" ar_append array3 array2[0] ar_append array4 array2[1] ar_erase ArraySorted 0 set isize to isize -1 elseif isize == 0 set nuked to 3 endif endif A little bit slow due to iSize to iSize -1, but at least something =\ Still curious maybe there's a less strange and faster way to achieve what I need. Uptade2 Just realized that I can't access such data as GetBaseDamage from array containing base objects, because they are stings. Oh dear...
DoctaSax Posted July 11, 2014 Author Posted July 11, 2014 There may be other solutions here, but I think maybe you should stick all the intel in a sub-array: [0][0] := base object 1 [0][1] := condition for the inv ref (I guess) [1][0] := base object 2 and so on and then sort your primary array with ar_customsort and a UDF that checks sv_compare between the names of the base forms. Either way, base forms & condition stay attached.
Xilandro Posted July 11, 2014 Posted July 11, 2014 There may be other solutions here, but I think maybe you should stick all the intel in a sub-array: [0][0] := base object 1 [0][1] := condition for the inv ref (I guess) [1][0] := base object 2 and so on and then sort your primary array with ar_customsort and a UDF that checks sv_compare between the names of the base forms. Either way, base forms & condition stay attached. I have no idea how to, I'm too tired to understand even simple things, but once I get some sleep - I will try. Thank you very much!
DoctaSax Posted July 11, 2014 Author Posted July 11, 2014 It's not the most simple of things, but there's an example in a spoiler in the tutorial. The ar_customsort function will take 2 elements of the source array (ie. 2 sub-arrays) and compare them. You define how it will decide if subarray a should go before subarray b in your main array by SetFunctionValue 1. so your comparison UDF should be something like scn UDF array_var a array_var b ref rForm1 ref rForm2 Begin Function {a b} let rForm1 := a[0] let rForm2 := b[0] if eval 1 == sv_compare $rForm1 $rForm2 ; the name of rForm1 is alphabetically earlier than the name of rForm2 SetFunctionValue 1 endif End
Xilandro Posted July 11, 2014 Posted July 11, 2014 Yeah, UDF example in tutorial is great, so I understand how it works. And thanks for new comparison for $forms =) The thing I can't get is this: [0][0] := base object 1 [0][1] := condition for the inv ref (I guess) How can I have an array with [0][0] and [0][1] keys? I'm definitely loosing logic. Tried something like this. for array ar_append array1[0][0] Formlet array1[0][0] := Form for stringmap let array1["0"][0] := Form Obviously, it's not working) I'm doing something very stupid, 100%
DoctaSax Posted July 11, 2014 Author Posted July 11, 2014 well, basically: let subarray[0] := form let subarray[1] := number let mainarray[0] := subarray result mainarray[0][0] == form mainarray[0][1] == number giving you nested arrays. Maybe I should make that a bit more explicit in the tutorial. you don't have to 'let' it all manually, just append subarrays to a main array with ar_append, ar_insert or however you go about it edit: the only way a let like this can work: let mainarray[0][0] := something is if you already initialized both the main & the sub
Xilandro Posted July 11, 2014 Posted July 11, 2014 Okay, got my rest, feel better now. And little bit confused. Looks like I need new subarray for every new form+number. Like subarray1, subarray2, subarray3, subarray4, etc. And I will end up with 50+ subarrays =\ That's a good way, but the more items - more subs. Anyway, thank you for your time good sir, I really appreciate your help =3
DoctaSax Posted July 11, 2014 Author Posted July 11, 2014 I still think it's the easiest way to sort the information however you want it (by name, condition etc) while keeping the intel linked. In the end, what you do in your inventory loop ends up with a ref var and a float var for each item, which you now stick in separate arrays. Instead, I'd just build a subarray with let subarray := ar_list rForm, fFloat, whateverelse Then ar_append your subarray to your main array. Doesn't really matter how many arrays you build, as long as you can manage them. Another benefit of doing it this way is you can easily attach more information to track, like item type etc, and not change your overall structure much. Whereas separate arrays obviously pose a problem if you start removing, adding, sorting through them, because you need to adjust every array you have to every change you do to any of them.
Guest Posted July 28, 2014 Posted July 28, 2014 Due to the temporary nature of arrays in UDFs, I'm storing an array which contains a list of references on an external quest (which contains all my variables). Anyway I must recreate this list from time to time. Any clue on how I can erase that array var? I explain better what I mean. - Scan for refs - ar_append quest.scanner scanned_ref - loop back ... - walk my quest.scanner, use ar_size to define its end ... - DELETE quest.scanner - re-scan the refs, and walk them again, etc. if I don't delete the quest.scanner, I risk that ar_append won't start from the first key/index, and also that I will have dirty values if the second scanner scans a smaller number of refs The first idea would be walking the array and Letting it with a not initialized ref var, but... isn't there something easier? EDIT: maybe ar_erase 0:(var defined by ar_size) could be a good idea? in this case, should it be (var defined by ar_size) or (var defined by ar_size - 1)? Last thing... When I walk an array, I use a Counter in a While Loop, as condition I use Counter < (var defined by ar_size). While this works, I feel that "Foreach" would the right function to inspect an array, but I can't understand in the tutorial and in NVSE documentation. If it's true, could someone provide an easy example?
Odessa Posted July 28, 2014 Posted July 28, 2014 The usual way I'd use to delete all elements of an array is just (re)call: let SomeArray := Ar_Construct "Array/Map/StringMap" Which makes the array_var refer to a new empty array, and the old array is deleted if no other var/array points at it. array_var Alpha array_var Beta let Alpha := Ar_List "cat" let Alpha := Ar_Construct "array" ; Alpha refers to a new empty array, and the array that used to store "cat" is automatically deleted let Alpha := Ar_List "cat" let Beta := Alpha let Alpha := Ar_Construct "array" ; Alpha is empty array ; Beta contains: "cat" You can use 'let SomeArray := Ar_Null' instead, if you want it to point at nothing, instead of an empty initialized array. See also, 'Ar_Resize' and other functions that altar an array in place (they don't return a new array), if you have multiple array_var/elements refering to the same array and want to change that for all of them. foreach is definitely the right way to expect elements in an array, see the GECK page: http://geck.bethsoft.com/index.php?title=Foreach
Guest tomm434 Posted September 16, 2014 Posted September 16, 2014 I've read the whole tutorial and every post. Ar_list can create array with up to 20 elements, I get it. But how much elements migth array have? (max) Can I add via AR_append up to 100 elements? 1000? These elements are supposted to be in array for a couple of seconds
DoctaSax Posted September 16, 2014 Author Posted September 16, 2014 afaik, you can add as many as you want
Guest tomm434 Posted September 16, 2014 Posted September 16, 2014 Really? that solves all of my problems, thanks!
Guest Posted November 25, 2014 Posted November 25, 2014 I need to know the key of an array, given the value (if it's present in the array of course). I could create a script that walks the array and compares the value at every step, but I was wondering if there's a proper function that already does it I attach a picture of something that could resemble what I'm looking for
Guest Posted January 5, 2015 Posted January 5, 2015 I must run 3 different UDFs which refill an array, basically they will scan 3 different types and fill the same table. I pass the type as parameter, something like MyUDF 31 means it scans type 31. All these refs must fill the same quest.array, but my problem is I don't know how to append it in the second UDF. Basically, I have a local array and a quest.array, because I can't do this: ar_append myquest.myarray my_scanned_ref So instead I do this: Let myarray := ar_Construct array Let myquest.myarray := myarray ar_append myarray my_scanned_ref And I saw it works fine, it's like if it replicates the quest.array in local. But I can't understand what happen the second time I run the UDF? will the first line (which initializes the local array) destroy the quest.array because of that second line?
DoctaSax Posted January 5, 2015 Author Posted January 5, 2015 Yeah, what you do there is pretty much delete the existing array before populating it again. In cases where I let a UDF populate a quest array var held elsewhere, I just pass it like this: call myUDF quest.arrayvar and capture it like this: scn myUDF array_var someVarName ; usually a shorter name than the original Begin Function {someVarName} let someVarName[someKey] := someValue ... End You can do the same with appending. Of course this means you have to construct the array somewhere else first before you pass it as a parameter to the populating UDF.
DoctaSax Posted January 26, 2015 Author Posted January 26, 2015 Changed a few things in the first section about persistence; in general, the rule should be that you explicitly ar_null array vars you don't need anymore instead of relying on the idea that nvse cleans them up once the script has run its course.
Odessa Posted January 27, 2015 Posted January 27, 2015 ! What has prompted this, have you found nvse is unreliable at cleaning them up in some contexts?
Guest Posted January 27, 2015 Posted January 27, 2015 I would like to understand when I must unitialize an array. Could you make some practical examples? for example, I scan a cell and fill an array with references, then I walk the array and do some code with these references. When I change cell I will re-scan the new cell, re-init the array with Ar_construct and fill with the new values: do I need to de-initialized between the first scan and the second one? Again: I have a bidimensional array with a list of datas. These datas are filled on GGL, but in general they are somewhat persistent datas. Do I need to uninitialize them everytime and then re-fill the array? If I reset their values with ar_construct, do I still need ar_null?
DoctaSax Posted January 27, 2015 Author Posted January 27, 2015 The fact is, I'm not sure. Some arrays that should be removed by the recycler just handling all arrays that lose a reference, haven't been. I spotted array IDs getting rather high in some spunk logs a while back, and corresponding .nvse files showed what looked like empty arrays being held for no reason I can see. On the whole, it's nothing too serious, I think, but obviously as people use arrays more and more, our practices must adapt until we can find a clearly identifiable cause. Recently I've been adapting spunk to explicitly ar_null arrays if: - I previously relied on a spell dispelling or a UDF just being done (local vars, including ones I've set to the UDF's function value) to clear things up - I previously re-let an already established array var to a new array, as in AJ's first example - they're iterators in foreach loops, which are supposedly uninitialized when the loop is done Obviously not if the whole point of the array is to stick around a while, containing data that I'll need a while. Not sure which one of those are actually to blame, I just wanted to eliminate every possible cause in my own work.
Guest Posted February 2, 2015 Posted February 2, 2015 Let MyArray[0] := MyRef0 Let MyArray[1] := MyRef1 Let MyArray[2] := MyRef2 These refs are all in-world. ar_erase MyArray 1 >>> this would erase the key 1. 1) What happens to the in world MyRef1 ? is it marked for delete? disabled? unaffected? 2) will MyRef2 take the slot of MyArray[1] ?
DoctaSax Posted February 2, 2015 Author Posted February 2, 2015 1) The ref itself is unaffected, all that's erased is the information that it's found in that array, under that key. 2) yes
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now