Can LINQ use binary search when the collection is ordered?

前端 未结 5 825
鱼传尺愫
鱼传尺愫 2020-12-01 02:56

Can I somehow \"instruct\" LINQ to use binary search when the collection that I\'m trying to search is ordered. I\'m using an ObservableCollection, pop

5条回答
  •  囚心锁ツ
    2020-12-01 03:38

    As far as I know, it's not possible with the built-in methods. However it would be relatively easy to write an extension method that would allow you to write something like that :

    var item = myCollection.BinarySearch(i => i.Id, 42);
    

    (assuming, of course, that you collection implements IList ; there's no way to perform a binary search if you can't access the items randomly)

    Here's a sample implementation :

    public static T BinarySearch(this IList list, Func keySelector, TKey key)
            where TKey : IComparable
    {
        if (list.Count == 0)
            throw new InvalidOperationException("Item not found");
    
        int min = 0;
        int max = list.Count;
        while (min < max)
        {
            int mid = min + ((max - min) / 2);
            T midItem = list[mid];
            TKey midKey = keySelector(midItem);
            int comp = midKey.CompareTo(key);
            if (comp < 0)
            {
                min = mid + 1;
            }
            else if (comp > 0)
            {
                max = mid - 1;
            }
            else
            {
                return midItem;
            }
        }
        if (min == max &&
            min < list.Count &&
            keySelector(list[min]).CompareTo(key) == 0)
        {
            return list[min];
        }
        throw new InvalidOperationException("Item not found");
    }
    

    (not tested... a few adjustments might be necessary) Now tested and fixed ;)

    The fact that it throws an InvalidOperationException may seem strange, but that's what Enumerable.First does when there's no matching item.

提交回复
热议问题