Jump to content
MechSlayer

Return true if the word it's inside the array

Recommended Posts

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

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;

 

  • Thanks 1

Share this post


Link to post
Share on other sites

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.

  • Thanks 1

Share this post


Link to post
Share on other sites

Could very well be, I have no idea

  • Thanks 1

Share this post


Link to post
Share on other sites

that's true, count is a bit faster because it doesn't have a index variable like forEachIndex

  • Thanks 1

Share this post


Link to post
Share on other sites

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. 

  • Thanks 1

Share this post


Link to post
Share on other sites

you should use the same code!

if u use exitWith with forEach then do this with count as well or ur tests are nonsense

  • Thanks 1

Share this post


Link to post
Share on other sites

Wait, you can exitWith in a count? 

Edit: oh yea, you can, nvm then, use count with an exitWith

Edited by stanhope
  • Thanks 1

Share this post


Link to post
Share on other sites
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.

  • Thanks 1

Share this post


Link to post
Share on other sites
_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

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

  • Like 2

Share this post


Link to post
Share on other sites

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.

  • Like 1

Share this post


Link to post
Share on other sites
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.

  • Like 3

Share this post


Link to post
Share on other sites
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;

 

  • Like 3

Share this post


Link to post
Share on other sites
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 by mrcurry
why, mobile site, why you no allow code format!!!

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×