Thread overview
Best way to check for an element in an array?
Apr 22, 2014
Taylor Hillegeist
Apr 22, 2014
Timothee Cour
Apr 22, 2014
Taylor Hillegeist
Apr 22, 2014
Ali Çehreli
Apr 23, 2014
FrankLike
Apr 23, 2014
FrankLike
April 22, 2014
So I find myself Doing this kind of thing very frequently. I have a Array of Somethings and i want to see if "something specific" is inside the array. I wrote a template for it. but is this the best way to do this kind of thing. I feel like it doesn't help with readability. Is there a better way? Maybe i missed something in the std library.

import std.stdio;

template FNDR(T){
    bool isIn(T Element, T[] Array){
        bool rtn=false;
        foreach(T ArrayElement; Array){
            if(Element==ArrayElement){
                rtn=true;
            }
        }
    return rtn;
    }
}

void main(string[] args)
{
    int[3] stuff=[0,1,2];
    if (FNDR!int.isIn(2,stuff))
    {
        writeln("Hello World!");
    }
}


Is there a way maybe to make it look like this?

import std.stdio;

template FNDR(T){
    bool contains(T[] Array,T Element){
        bool rtn=false;
        foreach(T ArrayElement; Array){
            if(Element==ArrayElement){
                rtn=true;
            }
        }
    return rtn;
    }
}

void main(string[] args)
{
    int[3] stuff=[0,1,2];
    if (stuff.contains(2)) // Much clean! stuff.FNDR!int.contains(2) doesn't work
    {
        writeln("Hello World!");
    }
}

I'm interested in what you guys think? what is the cleanest way to do this?
April 22, 2014
you can use stuff.canFind(2)

but sometimes it'd be more convenient to have the other way around (UFCS
chains etc);

how about:

bool isIn(T,T2...)(T needle, T2 haystack)
if(__traits(compiles,T.init==T2[0].init)){
  foreach(e;haystack){
    if(needle==e) return true;
  }
  return false;
}
unittest{
assert(1.isIn(3,1,2) && !4.isIn(3,1,2));
}





On Mon, Apr 21, 2014 at 8:25 PM, Taylor Hillegeist via Digitalmars-d-learn < digitalmars-d-learn@puremagic.com> wrote:

> So I find myself Doing this kind of thing very frequently. I have a Array of Somethings and i want to see if "something specific" is inside the array. I wrote a template for it. but is this the best way to do this kind of thing. I feel like it doesn't help with readability. Is there a better way? Maybe i missed something in the std library.
>
> import std.stdio;
>
> template FNDR(T){
>     bool isIn(T Element, T[] Array){
>         bool rtn=false;
>         foreach(T ArrayElement; Array){
>             if(Element==ArrayElement){
>                 rtn=true;
>             }
>         }
>     return rtn;
>     }
> }
>
> void main(string[] args)
> {
>     int[3] stuff=[0,1,2];
>     if (FNDR!int.isIn(2,stuff))
>     {
>         writeln("Hello World!");
>     }
> }
>
>
> Is there a way maybe to make it look like this?
>
> import std.stdio;
>
> template FNDR(T){
>     bool contains(T[] Array,T Element){
>         bool rtn=false;
>         foreach(T ArrayElement; Array){
>             if(Element==ArrayElement){
>                 rtn=true;
>             }
>         }
>     return rtn;
>     }
> }
>
> void main(string[] args)
> {
>     int[3] stuff=[0,1,2];
>     if (stuff.contains(2)) // Much clean! stuff.FNDR!int.contains(2)
> doesn't work
>     {
>         writeln("Hello World!");
>     }
> }
>
> I'm interested in what you guys think? what is the cleanest way to do this?
>


April 22, 2014
On Tuesday, 22 April 2014 at 03:57:33 UTC, Timothee Cour via Digitalmars-d-learn wrote:
> you can use stuff.canFind(2)
>
> but sometimes it'd be more convenient to have the other way around (UFCS
> chains etc);
>
> how about:
>
> bool isIn(T,T2...)(T needle, T2 haystack)
> if(__traits(compiles,T.init==T2[0].init)){
>   foreach(e;haystack){
>     if(needle==e) return true;
>   }
>   return false;
> }
> unittest{
> assert(1.isIn(3,1,2) && !4.isIn(3,1,2));
> }
>
I like it! I didn't know you could use templates like that! Question though? why doesn't canFind() work on statically allocated arrays?

import std.stdio;
import std.algorithm;

bool contains(T)( T[] haystack,T needle){
		 foreach(T e;haystack){
		   if(needle==e) return true;
		 }
	 return false;
}
unittest{
	assert([3,1,2].contains(1) && ![3,1,2].contains(4));
}

void main(string[] args)
{
    int[3] stuff=[0,1,2];
	if (stuff.contains(2))
    {
        writeln("Hello World!");
    }
	
	if (stuff.canFind(2)){ // No compile with stuff -> static
	    writeln("This Also WOrks");
	}
}


> On Mon, Apr 21, 2014 at 8:25 PM, Taylor Hillegeist via Digitalmars-d-learn <
> digitalmars-d-learn@puremagic.com> wrote:
>
>> So I find myself Doing this kind of thing very frequently. I have a Array
>> of Somethings and i want to see if "something specific" is inside the
>> array. I wrote a template for it. but is this the best way to do this kind
>> of thing. I feel like it doesn't help with readability. Is there a better
>> way? Maybe i missed something in the std library.
>>
>> import std.stdio;
>>
>> template FNDR(T){
>>     bool isIn(T Element, T[] Array){
>>         bool rtn=false;
>>         foreach(T ArrayElement; Array){
>>             if(Element==ArrayElement){
>>                 rtn=true;
>>             }
>>         }
>>     return rtn;
>>     }
>> }
>>
>> void main(string[] args)
>> {
>>     int[3] stuff=[0,1,2];
>>     if (FNDR!int.isIn(2,stuff))
>>     {
>>         writeln("Hello World!");
>>     }
>> }
>>
>>
>> Is there a way maybe to make it look like this?
>>
>> import std.stdio;
>>
>> template FNDR(T){
>>     bool contains(T[] Array,T Element){
>>         bool rtn=false;
>>         foreach(T ArrayElement; Array){
>>             if(Element==ArrayElement){
>>                 rtn=true;
>>             }
>>         }
>>     return rtn;
>>     }
>> }
>>
>> void main(string[] args)
>> {
>>     int[3] stuff=[0,1,2];
>>     if (stuff.contains(2)) // Much clean! stuff.FNDR!int.contains(2)
>> doesn't work
>>     {
>>         writeln("Hello World!");
>>     }
>> }
>>
>> I'm interested in what you guys think? what is the cleanest way to do this?

April 22, 2014
On 04/21/2014 09:22 PM, Taylor Hillegeist wrote:

> Question though? why doesn't canFind() work on statically
> allocated arrays?

That's an issue all of face from time to time. (Happened to me again last week. :) )

The reason is, algorithms like canFind work with input ranges and fixed-length arrays are not input ranges because they cannot support popFront(), which would reduce their length.

The solution is to use a full slice of the array by appending [] to it:

     if (stuff[].canFind(2)) {    // <-- note []

It works because now canFind() operates on a temporary slice (aka dynamic array).

Getting back to your original question, std.algorithm.find and canFind() are O(N) algorithms, which is too slow if you already have a sorted range.

When you indeed have a sorted range, you can pass it through assumeSorted() to create a SortedRange object so that you can take advantage of O(log N) algorithms like trisect() and friends (one of those friends is contains()):

import std.range;

void main()
{
    auto arr = [ 1, 2, 3, 3, 4, 5 ];
    auto result = arr.assumeSorted.trisect(3);

    assert(result[0].equal([ 1, 2 ]));
    assert(result[1].equal([ 3, 3 ]));
    assert(result[2].equal([ 4, 5 ]));
}

The search in that program is O(log N).

Ali

April 22, 2014
On Mon, 21 Apr 2014 23:25:39 -0400, Taylor Hillegeist <taylorh140@gmail.com> wrote:

> So I find myself Doing this kind of thing very frequently. I have a Array of Somethings and i want to see if "something specific" is inside the array. I wrote a template for it. but is this the best way to do this kind of thing. I feel like it doesn't help with readability. Is there a better way? Maybe i missed something in the std library.
>
> import std.stdio;
>

Change this:

> template FNDR(T){

To  this:

template isIn(T) {

>      bool isIn(T Element, T[] Array){
>          bool rtn=false;
>          foreach(T ArrayElement; Array){
>              if(Element==ArrayElement){
>                  rtn=true;
>              }
>          }
>      return rtn;
>      }
> }
>
> void main(string[] args)
> {
>      int[3] stuff=[0,1,2];
>      if (FNDR!int.isIn(2,stuff))

now: if(isIn(2, stuff))

see implicit function template instantiation (IFTI) in docs.

Also, using UFCS (Unified Function Call Syntax (I think)), we can do:

if(2.isIn(stuff))

Or if you swap the parameters, and perhaps rename your template/function:

if(stuff.contains(2))

>      {
>          writeln("Hello World!");
>      }
> }

-Steve
April 23, 2014
Hi,everyone,
This code must add the 'break',
import std.stdio;
int x=0;
template isin(T){
    bool isin(T[] Array,T Element){
        bool rtn=false;
        foreach(T ArrayElement; Array){
            if(Element==ArrayElement){
                rtn=true; break;      ← //here add break
            }
         x++;
        }
    return rtn;
    }
}

void main(string[] args)
{
    int[] stuff=[0,1,2,3,4,5,6,7,8,9,10];  ← //here declare int[]

    if (stuff.isin(2)) // Much clean!
    {
		writeln(x);
        writeln("Hello World!");
    }
}
----------------end---------------

Frank
April 23, 2014
Hi,everyone,
 It works maybe the best:

import std.stdio;

template isin(T){
    bool isin(T[] Array,T Element){
        foreach(T ArrayElement; Array){
            if(Element==ArrayElement){ return true;}
        }
    return false;
    }
}

void main(string[] args)
{
    int[] stuff=[0,1,2,3,4,5,6,7,8,9,10];

    if (stuff.isin(2))
    {
        writeln("Hello World!");
    }

	string[] strs =["Hello","world","hi","Everyone"];
	if(strs.isin("Hi"))
	{
		writeln("find Hi");
	}
	else
	{
		writeln("not find Hi from: "~strs);
	}
}

  ----------------end---------------

  Frank