Feature #26732

Filter array using predicate

Added by Muzzleflash over 3 years ago. Updated over 2 years ago.

Status:Closed Start date:12/02/2011
Priority:Normal Due date:
Assignee:Sickboy % Done:

100%

Category:-
Target version:v0.8.3
Component: Affected Version:
Close Reason:

Description

Didn't find this in the function library reference and thought that this function might be useful. It filters an array only keeping items for which a predicate is true. There are quite a bit of situation where you need this and would manually loop through the items and set objNull or something else and later subtract [ojbNull]. I know that there is a filter function already, however that has always been 'map' to me and this one 'filter'; not sure what to call this one now.

FUNCMAIN(Filter) = {
    PARAMS_2(_array,_filterCode);
    TRACE_2("filter",_array,_filterCode);

    private ["_result"];
    _result = [];
    _result resize (count _array);
    _rIdx = 0;
    {
        if (_x call _filterCode) then {
            _result set [_rIdx, _x];
            INC(_rIdx);
        };
    } forEach _array;
    _result resize _rIdx;
    _result
};

Say you wanted to find all APCs nearby:

_isApc = {
    getNumber (configFile >> "CfgVehicles" >> typeOf _this >> "transportSoldier") >= 3
};
_armoured = nearestObjects [player, ["Tank"], 70];
_apcs = [_armoured, _isApc] call CBA_fnc_realFilter;

Associated revisions

Revision 02c4b14c
Added by Sickboy over 3 years ago

~ ADDED: CBA_fnc_select and reject, array manipulation functions. closes #26732

Revision 02c4b14c
Added by Sickboy over 3 years ago

~ ADDED: CBA_fnc_select and reject, array manipulation functions. closes #26732

Revision 47fc4b99
Added by Sickboy over 3 years ago

fixed: Return type in documentation. refs #26732

Revision 47fc4b99
Added by Sickboy over 3 years ago

fixed: Return type in documentation. refs #26732

History

Updated by Sickboy over 3 years ago

  • Status changed from New to Assigned
  • Assignee set to Sickboy
  • Target version set to Future

Neat, imo 'reject'. http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-reject

Btw:
_rIdx = 0; and
_result set [_rIdx, _x];
INC(_rIdx);
could be replaced with PUSH(_result,_x); which uses count array as the insertion index, assuming the size of an array is simply a property on the array object, accessed by count, this should have no impact on performance.

Oh lol, but no, can't be used because you use resize :)

Updated by Muzzleflash over 3 years ago

PUSH uses an extra count? Then you would have to keep the result size 0 at first, meaning the array would get resized for every valid value instead of only twice as here.

Instead of "reject" what about using the word "accept" here? Else I would have to write my example: _isNotApc = {...};, can't remember the concept, but something that isStuff is easier to comprehend in code than isNotStuff.

Updated by Sickboy over 3 years ago

Cheers, I had updated already my comment ref PUSH :p

And you're right, this isn't reject / delete_if but the opposite; http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-select-21 / keep_if

Updated by Muzzleflash over 3 years ago

Yeah it's kinda confusing every language using it's own word. In Haskell and Python it's filter, in Ruby it's select, in .Net it's Where and so on.

I'm fine with either Accept, Select, and Where, (well filter too but that's taken :) ).

Updated by Sickboy over 3 years ago

  • Status changed from Assigned to Resolved
  • % Done changed from 0 to 100

Updated by Sickboy over 3 years ago

Cheers, i've added both reject and select.
How about an optional parameter to adjust the original array? For whatever purpose that might be useful?

Updated by Sickboy over 3 years ago

Fixed return type documentation (said string instead of array, my bad).

Btw PARAMS already includes TRACE by design.

Updated by Muzzleflash over 3 years ago

You mean like an optional in-place parameter? Sure - should default to false IMO then. You could probably just set _result = _array if inplace.

"Btw PARAMS already includes TRACE by design." - Does it also identify the function?

Have a couple of other functions which may or may not be useful to others:
ArrayFlatten/Concat: Removes one nested level, input: [ [A,B,C], [X,[Y,Z]], [P,Q,R] ] -> [A, B, C, X, [Y, Z], P, Q, R].
SelectRandomBias: Select random element from array using bias values: input ["A","B","C"],[5, 10, 20] -> one of: A/14%, B/28%, C/57%

Think that SelectRandomBias might be in BIS functions, but then that one is array element based meaning bias values of [1000, 2000, 4000] would create an array with 7000 elements just to pick a random. Whereas mine just takes time proportional to the number of elements.

If you think should be included I can post my version of them.

Updated by Sickboy over 3 years ago

"Btw PARAMS already includes TRACE by design." - Does it also identify the function?

Sure, logging includes: diag_frameNo, diag_tickTime, time, filename, linenumber

So filename instead of functionname, but that's better imo anyway.

Said functions sound interesting, though perhaps not widely used, can share, implement later.

Updated by Muzzleflash over 3 years ago

Should I write them in a new ticket?

What about the macros for optional/keyword parameters? Do they log?

Updated by Sickboy over 3 years ago

Yes, new ticket please.

DEFAULT_PARAM also logs yep :)

To review behavior add #define DEBUG_MODE_FULL before #include "script_component.hpp" and call the function, then review RPT.
(The output is not extensively formatted to reduce time required by script processor)

Updated by Sickboy over 3 years ago

  • Status changed from Resolved to Closed
  • Target version changed from Future to v0.8.3

Also available in: Atom PDF