tags:

views:

336

answers:

4

if i have array

array[0] = "jack"; array[1] = "jill"; array[2] = "lisa"; array[2] = "jackie";

and i want to find all elements with "ack" in it.

in this case it would return

"jack", "jackie".

what is the fastest way of doing this?

+5  A: 
array.Where(s => s.Contains("ack"));

(Cheerfully ignoring any localisation / string collation / case sensitivity issues.)

itowlson
is there anyway to make this case insensitive
ooo
s.ToLower().Contains("ack")
ChaosPandion
of course :) . . . .
ooo
Not that it matters but my original answer was the same as this but with .ToLower() included. :(
ChaosPandion
Or s.IndexOf("ack", StringComparison.OrdinalIgnoreCase) >= 0. The benefit of using IndexOf >= 0 with a StringComparison is that it allows you to control whether the comparison is ordinal or culture-respecting (e.g. if a string contained an accented upper-case A, would it match the "a" of "ack"?).
itowlson
+1  A: 

This should be a little bit faster than a LINQ solution.

var list = new List<string>();
foreach(string s in array)
{
    if ((s ?? "").Contains("ack"))
    {
        list.Add(s);
    }
}
ChaosPandion
using String.Empty instead of "" might make it a little faster
Yuriy Faktorovich
I don't think there'll be any appreciable speed difference -- the LINQ Where operator results in almost exactly the same code, just with an additional iterator class stuck in to handle deferred enumeration. Good catch on handling nulls though!
itowlson
That depends really. Some people consider shaving microseconds a good thing.
ChaosPandion
Although it is worth it to note that my crappy benchmarking tests showed it to be faster than the LINQ method, anyone know why it is? I used the following for the LINQ: array.Where(s => s.Contains("ack")).ToList()
Yuriy Faktorovich
Using Where creates a class called WhereArrayIterator which adds a layer of abstraction upon what I wrote here.
ChaosPandion
A: 

I don't really know C#. Here is a basic low-level approach in pseudo-code:

function boolean contains_string(string haystack, string needle)
  int needleIndex
  int haystackIndex
  for haystackIndex from 0 to haystack.length-needle.length
    for needleIndex from 0 to needle.length
      if haystack[haystackIndex+needleIndex] != needle[needleIndex]
        break
      end if
    end for
    if needleIndex == needle.length-1
      return TRUE
    end if
  end for
  return FALSE
end function

for each element in array
  if contains_string(element, "ack")
    new_array.push element
  end if
end for

Almost certainly contains bugs.

Joel
I guess you probably don't need to write your own Contains method. If feel a bit silly for posting this now. Maybe I should leave the C# questions to C# experts.
Joel
Down-voted. Thought that might happen. I'm sad now.
Joel
Looks like a mixture of VB, C, JavaScript. Very interesting.
ChaosPandion
It's too bad they didn't offer a reason.
Yuriy Faktorovich
A: 

I believe this should be faster than the LINQ solution.

IEnumerable<string> Containing(string[] xs, string sub) {
  foreach(string s in array)
  if (s.Contains(sub))
    yield return s;
}

I am assuming no null strings in xs.

cdiggins
I don't think this calls for yield. The odds are they will call .ToArray() anyway.
ChaosPandion