为什么不使用FindIndex()并以比FindAll()更快的迭代返回?

Mim*_*imi 1 c# list

我需要在列表项上测试的匹配条件非常耗时.而且,我知道条件将匹配不超过3项列表.

因此,检查所有列表项可能不是最好的主意; 然而,当我试图用FindFindex()最高的方法3次,测试了超过这些情况我以前FindAll()Where().

如何加快这种方法,或者最快找到三个匹配?

| #  Method            Time (sec)
| -------------------------------
| 1   Find (one-by-one)   42.37
| 2   FindAll             30.17
| 3   Where               30.53
Run Code Online (Sandbox Code Playgroud)

方法#1:

{
    int index;
    Predicate<T> predicate = t =>
        {
            ...
        };

    index = myCollection.FindIndex(predicate);

    if (index != -1)
    {
        T t1 = myCollection[index];
        myCollection.RemoveAt(index);

        index = myCollection.FindIndex(predicate);

        if (index != -1)
        {
            T t2 = myCollection[index];
            myCollection.RemoveAt(index);

            index = myCollection.FindIndex(predicate);

            if (index != -1)
            {
                T t3 = myCollection[index];

                return new T[] { t1, t2, t3 };
            }
            else
            {
                return new T[] { t1, t2 };
            }
        }
        else
        {
            return new T[] { t1 };
        }
    }
    else
    {
        return new T[] { };
    }
}
Run Code Online (Sandbox Code Playgroud)

方法#2:

{
    return myCollection.FindAll(t =>
    {
        ...
    }).ToArray();
}
Run Code Online (Sandbox Code Playgroud)

方法#3:

{
    return myCollection.Where(t =>
    {
        ...
    }).ToArray();
}
Run Code Online (Sandbox Code Playgroud)

编辑: 修改方法#1:

{
    int index;
    Predicate<T> predicate = t =>
        {
            ...
        };

    index = myCollection.FindIndex(predicate);

    if (index != -1)
    {
        T t1 = myCollection[index];

        index = myCollection.FindIndex(index + 1, predicate);

        if (index != -1)
        {
            T t2 = myCollection[index];

            index = myCollection.FindIndex(index + 1, predicate);

            if (index != -1)
            {
                T t3 = myCollection[index];

                return new T[] { t1, t2, t3 };
            }
            else
            {
                return new T[] { t1, t2 };
            }
        }
        else
        {
            return new T[] { t1 };
        }
    }
    else
    {
        return new T[] { };
    }
}
Run Code Online (Sandbox Code Playgroud)

Cod*_*ter 6

你的方法是慢,因为它遍历整个集合三次,因为你做删除操作也付出了代价(的"O(n),其中n为(计数-索引)",根据MSDN).

您可以通过调用FindIndex(int, predicate)重载来避开这两种情况,int在迭代源集合时会谴责起始位置.

所以要替换出现这种情况的地方:

myCollection.RemoveAt(index);

index = myCollection.FindIndex(predicate);
Run Code Online (Sandbox Code Playgroud)

有了这个:

index = myCollection.FindIndex(index + 1, predicate) 
Run Code Online (Sandbox Code Playgroud)

  • 所有方法现在都归结为:迭代集合并查找与谓词匹配的对象.最好的情况是,你的应该更快 - 如果许多元素与谓词相匹配,并且如果它们在开头.如果您的大量数据包含少于三个匹配项,则所有方法都必须迭代整个集合,并且需要花费同样的时间. (2认同)