Part of the code I'm working on is a sorted
List<someclass>
. It is sorted on a property (key) of the class, and we need to access the list to:
0) See if it contains an entry with a particular key.
1) If it does, retrieve or replace the item.
2) If not, add the item in the correct position (to keep it sorted).
What is desired is a method that will retrieve the index of the existing item or where the item ought to be. The
IndexOf
method of
List
is unsuitable for this, plus because we are assuming a sorted list, we can use a binary search in an effort to optimize the search.
Here is an implementation for the simple case where the list contains the same type as the key:
public static bool TryGetIndex<T>
(
this System.Collections.Generic.IList<T> List
,
T Sought
,
out int Index
) where T : System.IComparable<T>
{
bool result = false ;
Index = 0 ;
int lo = 0 ;
int hi = List.Count - 1 ;
while ( !result && ( lo <= hi ) )
{
Index = lo + ( hi - lo ) / 2 ;
int diff = Sought.CompareTo ( List [ Index ] ) ;
if (diff == 0 )
{
result = true ;
}
else if ( diff < 0 )
{
hi = Index - 1 ;
}
else
{
lo = ++Index ;
}
}
return ( result ) ;
}
However, that is not the situation I described earlier, so I have this version:
public delegate int Comparison<T,U> ( T Op1 , U Op2 ) ;
public static bool TryGetIndex<T,U>
(
this System.Collections.Generic.IList<U> List
,
T Sought
,
Comparison<T,U> Comparer
,
out int Index
)
{
bool result = false ;
Index = 0 ;
int lo = 0 ;
int hi = List.Count - 1 ;
while ( !result && ( lo <= hi ) )
{
Index = lo + ( hi - lo ) / 2 ;
int diff = Comparer ( Sought , List [ Index ] ) ;
if ( diff == 0 )
{
result = true ;
}
else if ( diff < 0 )
{
hi = Index - 1 ;
}
else
{
lo = ++Index ;
}
}
return ( result ) ;
}
This requires that you provide a method to perform the comparison. Here's an example where I'm trying to find a
DataRowView
with a particular value for
Name
:
delegate
(
string Op1
,
System.Data.DataRowView Op2
)
{
return ( System.StringComparer.InvariantCultureIgnoreCase.Compare
(
Op1
,
Op2 [ "Name" ]
) ) ;
}
Using this code to find the index of an existing item or the index where a non-existent item belongs allows you to add items where they belong to ensure that the list remains sorted. And the binary search is more efficient than a linear search, especially as the list grows large.