假设我有一个序列.

IEnumerable<int> sequence = GetSequenceFromExpensiveSource();
// sequence now contains: 0,1,2,3,...,999999,1000000

获取序列并不便宜,而且是动态生成的,我只想遍历它一次.

我想得到0-999999(即除了最后一个元素以外的所有元素)

我认识到我可以这样做:

sequence.Take(sequence.Count() - 1);

但这会导致在大序列上进行两次枚举.

有没有一个LINQ struct 可以让我这样做:

sequence.TakeAllButTheLastElement();

推荐答案

我不知道Linq解决方案——但你可以使用生成器(yield 率-回报率)轻松地自己编写算法.

public static IEnumerable<T> TakeAllButLast<T>(this IEnumerable<T> source) {
    var it = source.GetEnumerator();
    bool hasRemainingItems = false;
    bool isFirst = true;
    T item = default(T);

    do {
        hasRemainingItems = it.MoveNext();
        if (hasRemainingItems) {
            if (!isFirst) yield return item;
            item = it.Current;
            isFirst = false;
        }
    } while (hasRemainingItems);
}

static void Main(string[] args) {
    var Seq = Enumerable.Range(1, 10);

    Console.WriteLine(string.Join(", ", Seq.Select(x => x.ToString()).ToArray()));
    Console.WriteLine(string.Join(", ", Seq.TakeAllButLast().Select(x => x.ToString()).ToArray()));
}

或者作为丢弃最后n项的通用解决方案(使用注释中建议的队列):

public static IEnumerable<T> SkipLastN<T>(this IEnumerable<T> source, int n) {
    var  it = source.GetEnumerator();
    bool hasRemainingItems = false;
    var  cache = new Queue<T>(n + 1);

    do {
        if (hasRemainingItems = it.MoveNext()) {
            cache.Enqueue(it.Current);
            if (cache.Count > n)
                yield return cache.Dequeue();
        }
    } while (hasRemainingItems);
}

static void Main(string[] args) {
    var Seq = Enumerable.Range(1, 4);

    Console.WriteLine(string.Join(", ", Seq.Select(x => x.ToString()).ToArray()));
    Console.WriteLine(string.Join(", ", Seq.SkipLastN(3).Select(x => x.ToString()).ToArray()));
}

.net相关问答推荐

MSBuild:CopyToOutputDirectory不会将本机DLL复制到输出

使用React路由加载器获取数据不能正常工作

无法对.NET MAUI类库进行单元测试

NuGet 兼容与计算框架(Xamarin 和 .NET 6)

使用 DataDog 收集 OpenTelemetry 跟踪

如何在 Raspberry Pi 上托管 WASM 文件?

.Net MAUI Android 无法与 API localhost 对话

NonSerialized 属性

是否有任何 x 次的 for 循环的更短/更简单的版本?

.NET 4.0 中有内置的二叉搜索树吗?

如何在 C# 中创建 Word 文档?

C#:内存不足异常

如何在 WPF 中创建/制作圆角按钮?

DBNull 的意义何在?

基于多个字符分隔符拆分字符串

Convert.ToBoolean 和 Boolean.Parse 不接受 0 和 1

如何异步 Files.ReadAllLines 并等待结果?

形成两个列表并集的最简单方法

当我们按下 Enter 键时启动的 WPF 文本框命令

如何将 Excel 序列日期编号转换为 .NET DateTime?