当集合被排序时,LINQ 可以使用二分搜索吗? [英] Can LINQ use binary search when the collection is ordered?

查看:21
本文介绍了当集合被排序时,LINQ 可以使用二分搜索吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试搜索的集合被排序时,我能否以某种方式指示"LINQ 使用二分搜索.我正在使用 ObservableCollection,填充了有序数据,并且我正在尝试使用 Enumerable.First().在我的谓词中,我根据我的集合排序所依据的字段的值进行过滤.

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<T>, populated with ordered data, and I'm trying to use Enumerable.First(<Predicate>). In my predicate, I'm filtering by the value of the field my collection's sorted by.

推荐答案

据我所知,使用内置方法是不可能的.但是,编写一个允许您编写类似内容的扩展方法会相对容易:

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);

(当然,假设您的集合实现了 IList ;如果您不能随机访问项目,则无法执行二分查找)

(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)

这是一个示例实现:

public static T BinarySearch<T, TKey>(this IList<T> list, Func<T, TKey> keySelector, TKey key)
        where TKey : IComparable<TKey>
{
    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 ;)

它抛出 InvalidOperationException 的事实可能看起来很奇怪,但这就是 Enumerable.First 在没有匹配项时所做的.

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

这篇关于当集合被排序时,LINQ 可以使用二分搜索吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆