Array Subtraction

We have a list of 400+ approved mods in an array. When the player joins we create an array of their mods.
We want to return an array of the players’ mods that are not in the approved mods array.

Would it be faster to?:
Option 1
Use array subtraction to subtract the approved mods from the players mods which would return a list of unapproved mods.

private _NAKplayerMods = [1, 2, 6];
private _NAKapprovedMods = [1, 2, 3, 4, 5];
_NAKunapprovedMods = _NAKplayerMods  - _NAKapprovedMods; // _NAKunapprovedMods is [6]

Option 2
Do a ‘for,count,select’ to iterate through each of the players mods and check if it is IN the approved mods list if not add to a list of unapproved mods.

private _NAKplayerMods = [1, 2, 6];
private _NAKapprovedMods = [1, 2, 3, 4, 5];
_NAKunapprovedMods = [];
for "_i" from 0 to (count _NAKplayerMods ) -1 do {
    _NAKplayerModEntry = _NAKplayerMods select _i; 
	if !(_NAKplayerModEntry  in _NAKapprovedMods ) then {
        _NAKunapprovedMods pushback _NAKplayerModEntry ;
    };
};
_NAKunapprovedMods; // _NAKunapprovedMods is [6]

I am aware that additional code is needed for the example to make a working solution. The examples are only provided for clarification.

  • With this small test Option 1 is faster. .0016ms vs .0069ms
  • When looking at code from other developers I do not often see subtraction of arrays, which is partially why I am asking.

For those still learning these are the references.
https://community.bistudio.com/wiki/Array
https://community.bistudio.com/wiki/in
https://community.bistudio.com/wiki/pushBack

Have you tried running a test where the arrays aren’t pre-sorted (or does the array always come in sorted)?

Either way, option 2 definitely has to check repeatedly through the entire list of approved mods (very long) for each thing a player has, whereas option 1 might be getting away with stepping through the two arrays side-by-side post sorting and thus only going through each array once. It’s possible that starting with non-sorted arrays might slow down option 1 (possibly by forcing it to start with a sort).

Don’t quote me on that—I’m a technical writer, not a programmer—but that’s where I’d be looking next for evidence.

This was a re-post of an admin developer discussion. In the admin post, I posted the results.

FYI for anyone interested, for me, the array subtraction is quicker to write, easier to debug and is faster in performance.

I went ahead and made the approved mods array 400 elements and the players mods 100 elements, subtraction took 0.327654 ms vs a ‘for, count, select’ took 0.667557 ms.

Option one, in this circumstance will always go faster and use less utility. Option one takes [1, 2, 3, 4, 5] to locate the one “6” that is not in the list . Option two takes the first # “1” and looks to see if it is in the list, then moves to the next # “2”. So on, and so on until it reaches the end of the string.

Also looking at the second one, from what I can tell as soon as the list hits a mod that is not allowed it will init the pushback. As an example what if the user is using more then one unapproved mod?

Example:

private _NAKplayerMods = [1, 2, 6, 7];

Will it let me know if both “6” and “7” are unapproved with the 2nd option or will the pushback initiate on “6” and once I rejoin then it will init on “7”?

From my person experience the array subtraction will complete first then display the one or two (ECT.) unapproved mods, rather then pushing back after the first one it finds in the list.

Also looking at the second one, from what I can tell as soon as the list hits a mod that is not allowed it will init the pushback. As an example what if the user is using more then one unapproved mod?

Explanation of this code.

private _NAKplayerMods = [1, 2, 6];
private _NAKapprovedMods = [1, 2, 3, 4, 5];
_NAKunapprovedMods = [];
for "_i" from 0 to (count _NAKplayerMods ) -1 do {
    _NAKplayerModEntry= _NAKplayerMods select _i; 
	if !(_NAKplayerModEntry  in _NAKapprovedMods ) then {
        _NAKunapprovedMods pushback _NAKplayerModEntry ;
    };
};
_NAKunapprovedMods; // _NAKunapprovedMods is [6]

line 1 and 2 are just setting the variables for the test. In real code, these variables would be set other ways.
line 3 - Creating the variable array “_NAKunapprovedMods” and making sure that it is empty before I start adding values to it.
line 4 - This is the beginning of a for loop and the key to answering your question. It starts with the first element of the _NAKplayerMods and goes through all of them one at a time.
line 5 - This line sets the value of _NAKplayerModEntry to the X value of the array _NAKplayerMods. So the first loop the value would be the 1st value ‘1’, the second loop would be the 2nd value ‘2’ and the 3rd ‘6’. You need to keep in mind arrays start with 0 which is while in the ‘for’ statement we say ‘from 0’.
line 6 - Checks if, for this loop, if the value of _NAKplayerModEntry IS NOT in _NAKapprovedMods (the ‘!’ is not or negitive)
line 7 - If the value of _NAKplayerModEntry is not in _NAKapprovedMods add the current value to the array _NAKunapprovedMods
line 8 - Do the next loop or end if the count -1 for _NAKplayerMods has been reached.

So to answer your question the loop does not stop when the first value is found, it will loop through the values in _NAKplayerMods until it has done it ‘(count _NAKplayerMods ) -1’ times. There are multiple ways we could tell it to stop after the first, but in this case, as we want the player to know all of their unapproved mods, we go through them all.

That’s exactly what I expected, I was thinking it is a better end user experience to get a list of the unapproved mods rather then one at a time. With my personal experience I notice that users like convenience and streamlined processes. If a user has to connect more then twice to find the list of unapproved mods they have, its most likely they will not attempt a 3rd connection and move on to another location that they hope allows their set of mods.

I did an experiment with my work colleges witch they all know about now cause it came out in my EOY Performance Reporting. I built 2 apps that did the exact same thing except one was polished and had a more user friendly UI and provided everything they needed in one location. Where the other you had to use your knowledge of the business to understand what you were looking for. Needless to say even the developers refuse to use the more advanced application due to the lack of user friendly UI and convenience of all the data being available in one location. (This year long project has now pushed our business to look at all of our out word an in word facing applications to make them more accessible and user friendly.)