Puede probar el código que escribí a continuación. usando búsqueda binaria, por lo tanto, suponiendo que la lista/matriz está preordenada.
public static class ListExtensions
{
public static int GetAtMostIndex<TItem, TValue>(/*this*/ IList<TItem> list, TValue value, Func<TItem, TValue, int> comparer)
{
return GetAtMostIndex(list, value, comparer, 0, list.Count);
}
public static int GetAtLeastIndex<TItem, TValue>(/*this*/ IList<TItem> list, TValue value, Func<TItem, TValue, int> comparer)
{
return GetAtLeastIndex(list, value, comparer, 0, list.Count);
}
public static int GetAtMostIndex<TItem, TValue>(/*this*/ IList<TItem> list, TValue value, Func<TItem, TValue, int> comparer, int index, int count)
{
if (count == 0)
{
return -1;
}
int startIndex = index;
int endIndex = index + count - 1;
int middleIndex = 0;
int compareResult = -1;
while (startIndex < endIndex)
{
middleIndex = (startIndex + endIndex) >> 1; ///2
compareResult = comparer.Invoke(list[middleIndex], value);
if (compareResult > 0)
{
endIndex = middleIndex - 1;
}
else if (compareResult < 0)
{
startIndex = middleIndex + 1;
}
else
{
return middleIndex;
}
}
if (startIndex == endIndex)
{
compareResult = comparer.Invoke(list[startIndex], value);
if (compareResult <= 0)
{
return startIndex;
}
else
{
int returnIndex = startIndex - 1;
if (returnIndex < index)
{
return -1;
}
else
{
return returnIndex;
}
}
}
else
{
//todo: test
return startIndex - 1;
}
}
public static int GetAtLeastIndex<TItem, TValue>(/*this*/ IList<TItem> list, TValue value, Func<TItem, TValue, int> comparer, int index, int count)
{
if (count == 0)
{
return -1;
}
int startIndex = index;
int endIndex = index + count - 1;
int middleIndex = 0;
int compareResult = -1;
while (startIndex < endIndex)
{
middleIndex = (startIndex + endIndex) >> 1; ///2
compareResult = comparer.Invoke(list[middleIndex], value);
if (compareResult > 0)
{
endIndex = middleIndex - 1;
}
else if (compareResult < 0)
{
startIndex = middleIndex + 1;
}
else
{
return middleIndex;
}
}
if (startIndex == endIndex)
{
compareResult = comparer.Invoke(list[startIndex], value);
if (compareResult >= 0)
{
return startIndex;
}
else
{
int returnIndex = startIndex + 1;
if (returnIndex >= index + count)
{
return -1;
}
else
{
return returnIndex;
}
}
}
else
{
return endIndex + 1;
}
}
}
mismo [pregunta] (http://stackoverflow.com/questions/12412869/efficiently-find-nearest-dictionary-key), pero sin restricción en 'SortedList'. –
nawfal