Home   Help Search Login Register  

Author Topic: Deleting entry from array  (Read 1209 times)

0 Members and 1 Guest are viewing this topic.

Offline myke13021

  • Contributing Member
  • **
  • Myke
Deleting entry from array
« on: 03 Nov 2008, 22:02:50 »
Probably something pretty easy again but i don't get the way to solve this.

Ok, base settings:
I have an array which contains sub-arrays which are filled with classnames. Below an simplified example:
Code: [Select]
acep2_complete_class_array = [["SoldierMB","SoldierMMG"], ["SoldierPB","SoldierPTeamLeader"]];
Ok, the real array is much bigger but thats the only difference to this example.

Now as these arrays should only contain valid classnames, i try to remove anything that isn't a classname. This also includes variables booleans, other array or whatever doesn't fit in there. I want to do this to catch invalid entries before they may cause serious script failure and also this script is meant to be edited by user.
So i try to catch up all invalid types inside these arrays and delete them.

This works as long it is a STRING. In this case the isclass check works well and discards any classnames that aren't actually loaded classes (from addons).

But as soon the invalid classname isn't a string, my check fails. I tried with this array to find a working solution:
Code: [Select]
acep2_complete_class_array = [["SoldierMB","SoldierMMG"], ["SoldierPB","SoldierPTeamLeader", idiot]];

Now idiot is obviously not a classname (or might be but it isn't a string). What i have by now, based on the above array structur is this piece of code:
Code: [Select]
{
{
if (typename _x != "STRING") then {
ACEP2_DEBUG_INVALID_CLASSES = ACEP2_DEBUG_INVALID_CLASSES + [_x];
ACEP2_DEBUG_NON_FATAL_ERROR = ACEP2_DEBUG_NON_FATAL_ERROR + 1;
_acep2_get_invalid_pos = _acep2_array_to_check find _x;
_acep2_array_to_check set [_acep2_get_invalid_pos, nil];
_acep2_array_to_check resize ((count _acep2_array_to_check) - 1);
};
} foreach _x;
} foreach acep2_complete_class_array;
{
{
if (! isclass (configFile >> "CfgVehicles" >> _x)) then {
ACEP2_DEBUG_INVALID_CLASSES = ACEP2_DEBUG_INVALID_CLASSES + [_x];
ACEP2_DEBUG_NON_FATAL_ERROR = ACEP2_DEBUG_NON_FATAL_ERROR + 1;
_acep2_get_invalid_pos = _acep2_array_to_check find _x;
_acep2_array_to_check set [_acep2_get_invalid_pos, nil];
_acep2_array_to_check resize ((count _acep2_array_to_check) - 1);
};
} foreach _x;
} foreach acep2_complete_class_array;

The all-uppercase variables/arrays are for debugging use for the missionmaker to find errors faster as i show a hint if any errors come up and for the functionality they haven't anything to do with. Although i use ACEP2_DEBUG_INVALID_CLASSES as hint to see if the invalid entry was detected or not, as it would show up in there if it is detected. But so far no luck, this array remains empty.

Also by now there are 2 separate codeblocks as it is easier to get it working. Once it works as expected i will put those codes together but this is a sidenote yet.

So what am i doing wrong to get this entry out of the array? How do i get rid of this idiot (putting a Dollar in the PUN box)?

Oh, i also already tried the most easiest possible way:
Code: [Select]
_acep2_array_to_check = _acep2_array_to_check - [_x];
This also didn't worked at all.

And for completeness, ArmA doesn't throw an error on these lines, it just doesn't work as i want it to do.


Any help much appreciated.


Myke out

Offline Wolfrug

  • Addons Depot
  • Former Staff
  • ****
  • Official OFPEC Old Timer
Re: Deleting entry from array
« Reply #1 on: 03 Nov 2008, 22:47:19 »
TL;DR

No, seriously :D The basic jist of it all, as far as I got it, is that you want to delete an entry from an array of arrays. Or, more precisely, that you want an array that consists only of the proper kind of thingie.

The short answer is: just rebuild the arrays, sans the offending member. Create a loop, go through all the elements in all of the arrays and subarrays, and use them to create new, identical arrays, EXCEPTING the stuff you don't want (i.e., non-strings). So in your case I'd guess creating a quick loop that checks the typeName of each array entry and creates new ones as long as they're "STRING" should do it for you. :)

Sorry for not providing code, but that's basically the short answer. I've had this same problem with deleting unwanted stuff from arrays, and although I'm sure it's possible via more complicated ways, just rebuilding the array is the quickest and easiest way to do it. :)

Good luck!

Wolfrug out.
"When 900 years YOU reach, look as good you will not!"

Offline Spooner

  • Members
  • *
  • Mostly useless
    • Community Base Addons
Re: Deleting entry from array
« Reply #2 on: 03 Nov 2008, 22:50:08 »
Your
Code: [Select]
_acep2_get_invalid_pos = _acep2_array_to_check find _x;
_acep2_array_to_check set [_acep2_get_invalid_pos, nil];
_acep2_array_to_check resize ((count _acep2_array_to_check) - 1);
Does not trim out the element, since nil is a valid data type to put into the array. All you are doing is inserting nil and trimming off the last element, which is probably of a correct data type. Also, changing arrays while iterating through them is a no-no.

Code: (untested) [Select]
private "_valid";

// Iterate through the main array.
for "_i" from 0 to ((count acep2_complete_class_array) - 1) do
{
// Iterate through a COPY of the subarray (which prevents problems
// with altering something as you iterate through it).
{
if (typename _x == "STRING") then
{
if (isclass (configFile >> "CfgVehicles" >> _x)) then
{
_valid = true;
}
else
{
_valid = false;
};
}
else
{
_valid = false;
};

if (not _valid) then
{
ACEP2_DEBUG_INVALID_CLASSES = ACEP2_DEBUG_INVALID_CLASSES + [_x];
ACEP2_DEBUG_NON_FATAL_ERROR = ACEP2_DEBUG_NON_FATAL_ERROR + 1;

// Remove the broken data from the sub-array, which creates a new array,
// then replace the old sub-array with the "fixed" one.
acep2_complete_class_array set [_i,
(acep2_complete_class_array select _i) - [_x]];
};
} foreach ((acep2_complete_class_array select _i) + []);
};

As Wolfrug says though, it can be easier to rebuild arrays when you are doing this kind of operation on them...
[Arma 2] CBA: Community Base Addons
[Arma 1] SPON Core (including links to my other scripts)

Offline myke13021

  • Contributing Member
  • **
  • Myke
Re: Deleting entry from array
« Reply #3 on: 04 Nov 2008, 00:23:33 »
@Wolfrug & Spooner

Thanks for your input mates, much appreciated. And didn't thought there will be any replies so fast. Do you guys have a real life?  :D j/k mates.

Anyway, btt.
@Spooner
I've tested your code and it wasn't able to get rid off this idiot (PUN again). Might be because it is nothing, no text, no object and surely not a class. All i ever got was this well-known "Scalar Bool String Array..beatmetodeath" back from testing idiot for any typename.

So i made it less beautiful but at least it does the job.
As before i gathered all single arrays into one major array (while keeping them as independent arrays inside it as mixing up would have messed up everything) because i thought i could make nested foreach loops, i kept them standalone now.

So now i check all 44 arrays for its own and now it works with a simple isclass query. I also rebuild the arrays based on that as Wolfrug suggested. So i've ended up with a single script with 440 lines just to clean up those arrays from any unwanted scrap.

But this is not a problem since this check is done only once at mission start and is quickly finished.

And for completeness, here's the code i've finally used for one of those array. The other 43 parts are just copy/pasted and adjusted names:
Code: [Select]
_acep2_units_west_final = [];
{
if (isclass (configFile >> "CfgVehicles" >> _x)) then {
_acep2_units_west_final = _acep2_units_west_final + [_x];
} else {
ACEP2_DEBUG_INVALID_CLASSES = ACEP2_DEBUG_INVALID_CLASSES + [_x];
ACEP2_DEBUG_NON_FATAL_ERROR = ACEP2_DEBUG_NON_FATAL_ERROR + 1;
};
} foreach acep2_units_west;
acep2_units_west = _acep2_units_west_final;

Not beautiful code but it does the job.

So from my part, big thanks to you both. And as the problem was solved, this topic is

*CLOSED*


Myke out