Jump to content
  • 0
jaBote

Concerns about function that checks if a given element is in an array

Question

Hi people.

 

I've recently seen other implementations of a function which just checks if a given value (numeric or string) is member on an array. It feels strange to me since I've always thought the best and most straight-forward way for doing that is via the implementation I've always done, which works for both numeric and string variables (please don't mind the .@i inicialization to 0, I know it's useless but it just does reassure me):

// Tries to find if a given element is inside a selected array// @params: element, array// @returns: 1 if found, 0 otherwisefunction in_array {	.@total = getarraysize(getarg(1));	.@i = 0;	while (.@i < .@total) {		if (getarg(0) == getelementofarray(getarg(1),.@i))  {			return 1;		}	.@i++;	}	return 0;}

 

But I've recently seen @@Winterfox's implementation in a request's topic (this one), which is a rather creative two-line implementation (disregarding the other lines):

function	script	PVPLP_revertLevel	{	setarray .@maps$, "izlude", "pvp2", "pvp3";	getmapxy( .@map$, .@x, .@y, 0 );	if( !compare( implode( .@maps$, ":" ), .@map$ ) ) end;	atcommand "@blvl " + (PVPLP_TRUE_LEVEL - BaseLevel);}

 

Which makes me wonder about what one is more efficient and scalable. I guess Winterfox's implementation is somewhat faster (an implicit loop inside of implode and a string comparison is faster than a loop in which you compare elements one by one), but I've already used mine to find the index of the array which contains a given value (change return 1; to return i; and return 0; to return -1; (for not found) along with function's description (I named it array_pos, by the way).

 

P.S.: I guess it'd be a good idea if we made a suggestion for getting these functions (in_array and array_pos, whichever its implementation is) inside our repository? Implemented via source or as function, but we should also get repository public functions documented since no one I know makes use of them, or even gets them rewritten to make exactly_the_same_thing.

Share this post


Link to post
Share on other sites

6 answers to this question

Recommended Posts

  • 0

@@jaBote

 

Upon reading it again i realized i could have made it even a bit shorter.

function    script    PVPLP_revertLevel    {    setarray .@maps$, "izlude", "pvp2", "pvp3";    if( !compare( implode( .@maps$, ":" ), strcharinfo( PC_MAP ) ) ) end;    atcommand "@blvl " + (PVPLP_TRUE_LEVEL - BaseLevel);}

To the Topic:

 

A native in_array function would be a really great addition.

 

What also would be really good would be if getarraysize would return the real array size and not the highest index and a way to loop  trough a array via function instead of a index to make things like this possible:

...	mes "There are " + getarraysize( .demoSpecialMobIds ) + " which currently give you a special bonus."; 	mes "These mobs are the following: ";	while( .@mobId = next_element( .demoSpecialMobIds ) )		mes getmonsterinfo( .@mobId, MOB_NAME );	close;end;OnNPCKillEvent:if( !.demoSpecialMobIds[ killedrid ] ) end;... do some specialstuff for special mob ...end;OnInit:	.demoSpecialMobIds[ 1000 ] = 1;	.demoSpecialMobIds[ 1004 ] = 1;	.demoSpecialMobIds[ 1006 ] = 1;end;...

I just realized that this ".array[ idIndex ]" approach is a workaround for a lacking in_array function especially for integers except you want to extensivly utilize atoi. The benefit is like the solution with implode, it may be better performance wise.

 

Maybe a in_array function could solve both cases to make it more readable at all.

A next_element or phplike foreach loop would still be great though.

 

Such a kind of function would be great for functions which should work with integer and string values. I could imagine things like this:

 

for( .@i = 0; .@i <  getarraysize( getarg( 1 ) ); .@i++  )	mes getmonsterinfo( next_element( getarg( 0 ) ), next_element( getarg( 1 ) ) );

It would make it possible to either use the string constant or the number of specific informations to loop trough it via a function that doesn't care if it is a string or a number.

Edited by Winterfox

Share this post


Link to post
Share on other sites
  • 0

@@Angelmelody

 

That is correct, you need to use it with caution and this approach only is really usefull if you have to call that comparison a lot and / or the array is really big. Otherwise i think the performance benefit is really low.

Share this post


Link to post
Share on other sites
  • 0

@@Winterfox

it should be 

if( !compare( "#"+implode( .@maps$, "#" )+"#", "#"+strcharinfo( PC_MAP )+"#" ) ) end;

you should add the delimiter at the front and end of the string to get an accurate checking, which could fix the checking in Angelmelody post.

Share this post


Link to post
Share on other sites
  • 0

I prefer for loop w/o callfunction

.@arr_size = getarraysize(arraytetst);freeloop(.@arr_size > 510);for(.@i=0; arraytetst[.@i] != valtest ; .@i++ );freeloop(0);if(.@i  < .@arr_size )	mes " found!"else	mes "not found!";end;

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.