linq 面试问题:.Any()与if(.Length > 0)用于测试集合是否有元素

1u4esq0p  于 2023-05-11  发布在  其他
关注(0)|答案(9)|浏览(208)

在最近的一次采访中,我被问到.Any().Length > 0之间的区别是什么,以及为什么我在测试一个集合是否有元素时会使用这两种方法。
这让我有点吃惊,因为它似乎有点明显,但我觉得我可能错过了一些东西。
我建议当你只需要知道一个集合有元素时使用.Length,当你想过滤结果时使用.Any()
大概.Any()也会受到性能的影响,因为它必须在内部执行循环/查询。

zpgglvta

zpgglvta1#

Length只存在于某些集合类型中,例如Array
Any是一个扩展方法,可以用于任何实现IEnumerable<T>的集合。
如果存在Length,则可以使用它,否则使用Any
可能.Any()也会受到性能的影响,因为它必须在内部执行循环/查询。
Enumerable.Any不会循环。它获取迭代器并检查MoveNext是否返回true。下面是.NET Reflector的源代码。

public static bool Any<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        if (enumerator.MoveNext())
        {
            return true;
        }
    }
    return false;
}
nwnhqdif

nwnhqdif2#

我猜面试官可能是想问关于检查Any()Count() > 0(而不是Length > 0)的问题。
基本上是这样的
Any()将通过枚举单个项来有效地尝试确定集合是否有任何成员。(有一个重载来检查使用Func<T, bool>的给定条件,但我猜面试官指的是不带参数的Any()版本。)这使得它是O(1)。
Count()将首先检查LengthCount属性(来自T[]ICollectionICollection<T>)。这通常是O(1)。但是,如果这不可用,它将通过枚举整个集合来计算集合中的项。时间复杂度O(n)
一个CountLength * 属性 *,如果可用的话,很可能是O(1),就像Any()一样,并且可能会表现得更好,因为它根本不需要枚举。但是Count() * 扩展方法 * 并不能确保这一点。因此,它有时是O(1),有时是O(n)。
假设你正在处理一个没有描述性的IEnumerable<T>,并且你不知道它是否实现了ICollection<T>如果你只是想确保集合不是空的,那么你最好使用Any()而不是Count() > 0

iibxawm4

iibxawm43#

Length是数组类型的属性,而Any()Enumerable的扩展方法。因此,只能在处理数组时使用Length。当使用更抽象的类型(IEnumerable<T>)时,可以使用Any()。

fjnneemd

fjnneemd4#

.长度...系统.数组.任何... IEnumerable(扩展方法)。
我更喜欢用“长度”,只要我能找到它。属性比任何方法调用都要轻量级。
不过,“Any”的实现不会做任何事情,除了下面提到的代码。

private static bool Any<T>(this IEnumerable<T> items)
        {
            return items!=null && items.GetEnumerator().MoveNext();
        }

还有,一个更好的问题本可以是“。计数”和“。长度”的区别,怎么说:)。

k4aesqcs

k4aesqcs5#

我认为这是一个更普遍的问题,即如果我们有两种表达方式,我们该选择什么。在这种情况下,我建议这样说:“要具体”引用彼得·诺维格在他的书PAIP
要具体,就是说用最恰当的方式描述你正在做的事情。所以你想说的是:

collection.isEmpty()

如果你没有这样的结构,我将选择社区使用的常见习语。对我来说,.Length > 0不是最好的,因为它强制你可以调整对象的大小。假设你实现了无限列表。.Lenght显然不起作用。

8yoxcaq7

8yoxcaq76#

听起来很像这个关于.Count和. any之间的差异的Stackoverflow问题,用于检查结果的存在:检查Linq-to-xml中是否存在结果
在这种情况下,最好使用Any,然后使用Count,因为Count将迭代IEnumerable的所有元素

uelo1irk

uelo1irk7#

我们知道.Length只用于数组,而.Any()用于IEnumerable的集合。
您可以将.Count替换为.Length,在处理IEnumberable的集合时也会遇到同样的问题
.Any()和.Count都在开始枚举数之前执行空检查。在性能方面,它们是一样的。
对于数组,假设我们有以下行:

int[] foo = new int[10];

这里是foo,长度是10。虽然这是正确的,但它可能不是您想要的答案,因为我们还没有向数组中添加任何内容。如果foo为null,则会抛出异常。

xzabzqsa

xzabzqsa8#

什么是讨论。所有的源代码都是可用的,所以你知道:如果你使用的示例具有Length或Count属性,那么你的时间复杂度总是O(1)。该值是示例的成员,您可以直接与任何其他值进行比较。它只是两个值之间的比较操作。
扩展方法Any()总是首先创建一个新的迭代器,并尝试获取第一个元素。它也是O(1),但由于创建了一个新的迭代器,每次调用Any()时都会为这个迭代器分配少量内存。在迭代器使用的MoveNext()的实现中,有2个比较操作和一个基于索引的列表访问,因为MoveNext还保存了成员内部迭代的当前值(参见List的枚举器的实现),这就是为什么如果可以使用,您应该首选使用Count或Length属性。

fafcakar

fafcakar9#

.Length遍历集合并返回元素数。复杂度为O(n)
.Any检查集合是否至少有一个项。复杂度为O(1)

相关问题