【问题标题】:Is string.ElementAt() O(1)?string.ElementAt() 是 O(1) 吗?
【发布时间】:2010-11-30 20:30:43
【问题描述】:

在备注下,it

如果源的类型实现了 IList,则该实现用于获取指定索引处的元素。否则,此方法获取指定元素。

String 没有实现IList<T>。这是否意味着如果我声明类似,这将是一个O(n) 操作,

IEnumerable<char> myString = "stringy";

?

【问题讨论】:

  • 这引出了一个有趣的问题:为什么string 没有实现IList&lt;char&gt;
  • @CodeInChaos:我也想过这个问题,但我认为这是因为字符串是不可变的。不能有那些 AddRemove 方法。
  • @Ralph IList 有一个 IsReadOnly 属性。并且突变方法将被显式实现(因此它们不会出现在string 本身)并抛出NotSupportedException。我仍然认为 .net 中没有 Collection/List 的只读接口是一个设计错误。
  • @CodeInChaos:因为我没有字符串,所以我有一个IEnumerable&lt;char&gt;可能恰好是一个字符串。或者一个 List,或者一个数组,或者你有什么。
  • @Brian:你说的是显而易见的 :) 就像我说的,我不知道内部类型,我只知道我有一个 IEnumerable 可能恰好是一个字符串。是的,我可以在致电ElementAt() 之前手动检查它,但这是我不想在任何地方都采取的额外步骤。可以编写我自己的扩展程序......但是......你知道,当你因为标准中的一个小缺陷而不得不做这些小事情时,这很糟糕。

标签: c# linq string ienumerable


【解决方案1】:

ElementAt 应用于 string 类型时将是 O(N) 操作。它没有实现IList&lt;char&gt;,因此ElementAt 不会对其进行任何优化,而是通过IEnumerable&lt;char&gt; 进行枚举,直到达到指定的索引。

【讨论】:

  • 字符串没有特殊情况实现?太烂了:(
  • @Ralph 通常,LINQ 方法不会为具体类型实现特殊情况,而是为接口实现。
  • String 太常见了! :p 它在我心中仍然很特别,即使 linq 不会认出它。
【解决方案2】:

由于 string 没有实现 IListIEnumerable&lt;char&gt; ElementAt 将执行以下代码:

using (IEnumerator<TSource> enumerator = source.GetEnumerator())

字符串上的 GetEnumerator 检索 CharEnumerator,正如您所假设的那样,它是 O(n)。

如果您想要更好的实现,请创建自己的扩展方法

public static class StringExt
{
    public static char ElementAt(this string input, int index)
    {
        if (index < input.Length) return input[index];
        throw new IndexOutOfRangeException();
    }
}

我假设是 O(1),但很难说,因为字符串上的索引访问器是在不安全的代码中完成的。

【讨论】:

  • 仅供参考,如果您的扩展方法仅扩展字符串,那么它是无用的;)
  • 您可以将其重命名为 ElementsAt,它会在 Linq 之前选择您的具体实现。然后根据需要添加具体版本。
猜你喜欢
  • 2010-09-20
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
  • 2010-11-06
  • 1970-01-01
相关资源
最近更新 更多