views:

77

answers:

3

I have an array of a certain type. Now I want to find an entry where a certain condition is met.

What is the preferred way to do this with the restriction that I don't want to create a temporary object to find, but instead I only want to give a search condition.

MyClass[] myArray;
// fill and sort array..
MyClass item = Array.BinarySearch(myArray, x=>x.Name=="Joe"); // is this possible?

Maybe is it possible to use LINQ to solve it?

EDIT: I know that it works on normal collections, but I need it to work for BinarySearch.

+3  A: 

Just use FirstOrDefault (or SingleOrDefault, if unique).

 var myItem =  myArray.FirstOrDefault( x => x.Name == "Joe" );

Or if you want to force a BinarySearch and you know that the array is sorted

 var myItem = Array.BinarySearch( myArray,
                                  new MyClass { Name = "Joe" },
                                  new MyClassNameComparer() );

where MyClassNameComparer is IComparer<MyClass> and compares based on the name property.

If you don't want any temporary object -- I assume that a constant string is ok, otherwise you're lost -- then you can use.

 var myItem = Array.BinarySearch( myArray,
                                  "Joe",
                                  MyClassOrStringComparer() );

Where MyClassOrStringComparer is able to compare a string to a MyClass object (and vice versa).

public class MyClassOrStringComparer
{
     public int Compare( object a, object b )
     {
         if (object.Equals(a,b))
         {
             return 0;
         }
         else if (a == null)
         {
             return -1;
         }
         else if (b == null)
         {
             return 1;
         }

         string aName = null;
         string bName = null;

         if (a is string)
         {
             aName = a;
         }
         else
         {
             aName = ((MyClass)a).Name;
         }

         if (b is string)
         {
             bName = b;
         }
         else
         {
             bName = ((MyClass)b).Name;
         }

         return aName.CompareTo( b.Name );
   }
tvanfosson
the first one is no binarysearch. the second one creates a temporary object to find which I don't want to create, as I stated in the question.
codymanix
Sorry. I misread your question as not wanting to create a temporary array. I think your restriction on not creating a temporary object is misguided as it makes the solution easier. Otherwise you need to create a more complicated comparer that can compare a MyClass object to a string.
tvanfosson
@codymanix -- note I've updated my answer with a string/MyClass comparer that I think meets your requirements -- except it uses a temporary string object. :-)
tvanfosson
+2  A: 

No, BinarySearch does not contains overload with Comparision<> parameter. You can use LINQ method instead:

MyClass item = myArray.FirstOrDefault(x => x.Name == "Joe");
Nagg
this is no binarysearch.
codymanix
+1  A: 

BinarySearch can only be used when the array is sorted, and only when searching for a particular value of the sort key. So this rules out use of an arbitrary predicate.

Ben Voigt