快速查找已排序列表中的项目索引

时间:2011-10-03 10:52:41

标签: c# .net list

我有一个对象:

public class MyObject
{
int id;
string value;
}

我也有一个清单:

List<MyObject> list = new List<MyObject>;
for(int i=0;i;i<100000;i++)
{
list.Add(new MyObject(i, string.Format("Item {0}", i));
}

列表将是:

1, "Item 1"
2, "Item 2"
....
99999, "Item 99999"

此列表是按ID字段排序的排序列表。请注意,这是一个描述排序列表的示例,它不像上面的示例那样简单。

我想根据ID字段找到一个有序列表项。我不知道.NET Framework是否支持在没有枚举的情况下快速搜索有序列表。

由于列表很重要,我对性能很感兴趣。感谢。

最好的问候。

8 个答案:

答案 0 :(得分:6)

您可以使用binary search

您可以使用built-in implementation,提供可在您的类型id属性上进行比较的自定义IComparer<T>

var objToFind = new MyObject { id = 42 };

int foundIndex = yourList.BinarySearch(objToFind, new MyObjectIdComparer());

// ...

public class MyObjectIdComparer : Comparer<MyObject>
{
    public override int Compare(MyObject x, MyObject y)
    {
        // argument checking etc removed for brevity

        return x.id.CompareTo(y.id);
    }
}

答案 1 :(得分:3)

四个选项:

  • 如果您的列表始终包含ID为1 ... n的项目,那么您可以这样做:

    MyObject foo = list[id - 1];
    
  • 您可以填充Dictionary<int, MyObject>

  • 您可以MyObject实施IComparable<T>IComparable(按ID排序)并使用List<T>.BinarySearch,提供具有所需ID的虚拟MyObject
  • 您可以自己实施二进制搜索 - 这样做并不是非常困难

请注意,如果您采用最后一种方法,可能希望以通用方式执行此操作作为扩展方法,以便您以后可以重复使用它:

// Optionally another overload with an IComparer<TKey>
public static TItem ProjectedBinarySearch<TItem, TKey>(
    this IList<TItem> list,
    Func<TItem, TKey> projection)
{
    // Do the binary search here.
    // TODO: Decide what to do if you can't find the right value... throw
    // an exception? Change the return type to return the *index* instead of the
    // value?
}

答案 2 :(得分:2)

我假设它实际上不是1:1的数组索引和ID字段(就像你的例子中一样),或者你可以使用[] -method来找到它。

选项1将是将其添加到词典中,并使用ID字段作为键。

选项2是编写一个临时二进制搜索,从数组中间开始,检查当前id是更大,更小还是正确。然后使用新的子数组再次执行此操作,直到找到您的ID。

答案 3 :(得分:0)

而不是蛮力,开端,搜索,你可以实现某种二进制除法,这应该可以很好地加速它。或者使用词典类型?

答案 4 :(得分:0)

你可以简单地使用.Find()来查找列表中的项目,而无需明确枚举:

http://msdn.microsoft.com/en-us/library/x0b5b5bc.aspx

编辑:实际上,仔细查看它看起来像是线性搜索,可能不是你想要的。

答案 5 :(得分:0)

关于您ID的索引是ID - 1。但是,如果您删除了项目,那么这种方式将无效。然后,您可以使用Binary search,您列出的提供已排序。因此,您必须始终对其进行排序,否则您将使用无效的Linear search

答案 6 :(得分:0)

看看Linq

using System.Linq;

从列表中获取可查询(通常通过.AsQueryable()调用)

在获得的Queryable

上应用.Select()
var c = queryable.Select (x => x.field == 999)

答案 7 :(得分:0)

对于那些根据它的标题遇到这个问题的人(快速查找排序列表中项目的索引),您可能有兴趣知道SortedList&lt; TKey,TValue&gt;有以下两种方法: -

    public int IndexOfKey(TKey key);
    public int IndexOfValue(TValue value);

和SortedList有: -

    public virtual int IndexOfKey(object key);
    public virtual int IndexOfValue(object value);