MechSlayer 18 Posted March 21, 2019 I have this array Cars = ["Car_1","Car_2","Car_3"] How can I make this ("Car" in Cars) return true without typing _1 or _2 ? Share this post Link to post Share on other sites
stanhope 409 Posted March 21, 2019 A foreach loop with a find comes to mind, but there's probably other ways of doing it. private returnVal = false; { if ( toLower(_x) find "car" > -1) exitWith { returnVal = true; }; } forEach Cars; 1 Share this post Link to post Share on other sites
beno_83au 1362 Posted March 21, 2019 You can use a combination of find with the alternate syntax and count. I think it's also a good idea to at least consider using toLower or toUpper when searching strings. Not always necessary, but worth considering. @stanhope I believe count is supposed to be faster than forEach. I remember reading that here somewhere a while ago. 1 Share this post Link to post Share on other sites
stanhope 409 Posted March 21, 2019 Could very well be, I have no idea 1 Share this post Link to post Share on other sites
sarogahtyp 1105 Posted March 21, 2019 that's true, count is a bit faster because it doesn't have a index variable like forEachIndex 1 Share this post Link to post Share on other sites
stanhope 409 Posted March 21, 2019 Actually @sarogahtyp and @beno_83au just did some testing. I used the following code: private _returnVal = false; { if ( toLower(_x) find "car" > -1) exitWith { _returnVal = true; }; } forEach Cars; hint str _returnVal; /*****************************************/ private _returnVal = false; private _cnt = { toLower(_x) find "car" > -1 } count Cars; if (_cnt > 0) then { _returnVal = true; }; hint str _returnVal; Cars is an array with 50 elements. 49 times the string "mar" and 1 string "car", all lower case. In my first test car was the very last element of the array. In that case the foreach took 0.145582 ms and the count 0.12865 ms. However, in a second test I put the car as the very first element of the array (still 50 elements). Now the foreach took 0.0472 ms and the count 0.158479 ms. To get a more reliable result I'd have to redo those tests several times. But I'd say that if you don't know how long the array will get or the rough position of the element you're looking for use count, if you're pretty sure it's gonna be among the first few elements in a long array use foreach with the exitwith. 1 Share this post Link to post Share on other sites
sarogahtyp 1105 Posted March 21, 2019 you should use the same code! if u use exitWith with forEach then do this with count as well or ur tests are nonsense 1 Share this post Link to post Share on other sites
stanhope 409 Posted March 21, 2019 (edited) Wait, you can exitWith in a count? Edit: oh yea, you can, nvm then, use count with an exitWith Edited March 21, 2019 by stanhope 1 Share this post Link to post Share on other sites
gc8 970 Posted March 21, 2019 4 minutes ago, sarogahtyp said: why not? I'd advice to be careful using exitWith in those commands. Have you tested your code? I had problem in select once, when using exitWith in there, it messed up the result. 1 Share this post Link to post Share on other sites
MechSlayer 18 Posted March 21, 2019 _array = getCursorObjectParams select 1; // ["door_4","door_4_action"] _count = count _array - 1; // Number of elemnts - 1 for "_i" from 0 to _count do //Change _i from 0 to the count result { _a = _array select _i; //Select each element _a = toLower _a; _find = str _a find "door"; //Check if "door" it's inside }; This seems to work pretty fine, Thanks all! Share this post Link to post Share on other sites
Grumpy Old Man 3540 Posted March 21, 2019 findIf might be even faster than forEach or count. Edit: Did some quick worst/best case tests: //worst case scenario TEST_array = []; for "_i" from 0 to 9998 do { TEST_array pushBack "man"; }; TEST_array pushBack "car"; //tests: TEST_array find "car" > -1;// 0.163265 ms {_x isEqualTo "car"} count TEST_array > -1;// 5.31746 ms TEST_array findIf {_x isEqualTo "car"} > -1;// 5.53591 ms ///////////////////////////////////////////////////////// //best case scenario TEST_array = ["car"]; for "_i" from 0 to 9998 do { TEST_array pushBack "man"; }; //tests: TEST_array find "car" > -1;//0.0009 ms TEST_array findIf {_x isEqualTo "car"} > -1;// 0.0016 ms {_x isEqualTo "car"} count TEST_array > -1;// 5.25654 ms ///////////////////////////////////////////////////////// //"car" is element 5000/10000, rest all "man" TEST_array find "car" > -1;// 0.0841 ms TEST_array findIf {_x isEqualTo "car"} > -1;// 2.67914 ms {_x isEqualTo "car"} count TEST_array > -1;// 5.26316 ms Well didn't expect that, so in any case find seems to be fastest, unless I'm missing something. Cheers 2 Share this post Link to post Share on other sites
pierremgi 4739 Posted March 21, 2019 As reminder: ["Car_1","Car_2","Car_3"] select {["car",_x] call Bis_fnc_inString}; // returns the array of cars ["Car_1","Car_2","Car_3"] findIf {["car",_x] call Bis_fnc_inString} >-1 // condition for "car" presence. 1 Share this post Link to post Share on other sites
Dedmen 2590 Posted March 22, 2019 14 hours ago, Grumpy Old Man said: Well didn't expect that, so in any case find seems to be fastest, unless I'm missing something. Nope you're not missing something, and it completely makes sense. find is completely in engine. findIf has to call back to SQF code, set up a new scope with a new local namespace everytime to call the code, then clear the local namespace and remove the scope again, and then start fresh for next execution. That's alot of work. 3 Share this post Link to post Share on other sites
Larrow 2801 Posted March 22, 2019 18 hours ago, Grumpy Old Man said: Well didn't expect that, so in any case find seems to be fastest, unless I'm missing something. Seems reasonable. Only thing your missing is find by sub string as per OP. @pierremgi Using select[ index, count ] is faster than BIS_fnc_inString. _find = "Car"; _array = [ "Car_1", "Car_2", "Car_3", "Car_4" ]; _result = _array findIf { _x select[ 0, count _find ] == _find } > -1; 3 Share this post Link to post Share on other sites
mrcurry 470 Posted March 23, 2019 (edited) 20 hours ago, Larrow said: Seems reasonable. Only thing your missing is find by sub string as per OP. @pierremgi Using select[ index, count ] is faster than BIS_fnc_inString. _find = "Car"; _array = [ "Car_1", "Car_2", "Car_3", "Car_4" ]; _result = _array findIf { _x select[ 0, count _find ] == _find } > -1; +1 As a side note for later readers: Replace select with find and the previously mentioned toLower (or toUpper) to cover use cases where the string structure is not guaranteed i.e. when Cars = ["a_car_1", "car_2", "3_car"] is a thing. Iterating on @Larrow's example: _find = toLower "Cars"; _array = ["a_Car_1", "Car_2", "3_car"]; _result = _array findIf { toLower _x find _find > - 1 } > -1; Edited March 23, 2019 by mrcurry why, mobile site, why you no allow code format!!! Share this post Link to post Share on other sites