You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现不重启枚举的重复LINQ查询解析重复模式字符串?

用LINQ实现重复模式字符串的分段解析

要实现你想要的Repeat方法,核心是维护一个共享的枚举器,让每次LINQ操作都从上一次处理结束的位置继续推进,而不是从头遍历整个字符串。以下是完整的实现代码:

1. 实现Repeat扩展方法

创建静态扩展类,实现Repeat方法:

using System;
using System.Collections.Generic;
using System.Linq;

public static class EnumerableExtensions
{
    // 重复对同一个枚举器应用selector,直到枚举耗尽,每次返回selector的处理结果
    public static IEnumerable<TResult> Repeat<T, TResult>(this IEnumerable<T> source, Func<IEnumerable<T>, TResult> selector)
    {
        using var enumerator = source.GetEnumerator();
        
        while (true)
        {
            // 检查是否还有剩余元素可处理
            if (!enumerator.MoveNext())
                yield break;
            
            // 创建一个从当前枚举位置开始的可枚举序列,消费时会推进共享枚举器
            IEnumerable<T> remaining = EnumerateFromCurrent(enumerator);
            
            // 应用传入的LINQ逻辑,获取当前段的结果
            TResult result = selector(remaining);
            yield return result;
        }
    }

    // 辅助方法:从枚举器当前位置开始枚举,直到结束
    private static IEnumerable<T> EnumerateFromCurrent<T>(IEnumerator<T> enumerator)
    {
        yield return enumerator.Current;
        while (enumerator.MoveNext())
        {
            yield return enumerator.Current;
        }
    }
}

2. 实现你的GetContentOfEachP方法

现在可以直接用你设想的LINQ链式调用:

using Newtonsoft.Json.Linq;

public JToken[] GetContentOfEachP(string text)
{
    return text
        .Repeat(enumerable =>
            enumerable
                .SkipWhile(c => c != ':')   // 跳过键名部分(直到遇到冒号)
                .Skip(1)                    // 跳过冒号本身
                .TakeWhile(c => c != '\r')  // 提取冒号到\r之间的内容
                .ToArray()
        )
        .Select(charArray => JToken.Parse(new string(charArray)))
        .ToArray();
}

3. 测试代码

调用方式和你预期的一致:

var input = "p0:{foo:bar}\r\np1:1234\r\np2:abcd";
foreach (var p in GetContentOfEachP(input))
{
    Console.WriteLine(p.ToString());
}

输出结果:

{
  "foo": "bar"
}
1234
"abcd"

关键逻辑说明

  • 共享枚举器:Repeat方法内部只创建一个枚举器,所有分段处理都复用这个枚举器,确保每次处理都从上一次结束的位置继续。
  • EnumerateFromCurrent辅助方法:把当前枚举器包装成可枚举序列,让SkipWhile/TakeWhile等LINQ方法可以直接消费,同时自动推进枚举器的位置。
  • 分段推进:每次调用selector后,枚举器已经停在当前段的末尾(比如\r的位置),下一次循环会跳过这个位置,继续处理下一段。

关于生产环境的说明

正如你提到的,生产环境中用text.Split("\r\n")再逐个处理的方式更简洁易读,维护成本更低。这个LINQ实现更多是满足技术探索的好奇心,展示如何通过控制枚举器来实现分段遍历。

内容的提问来源于stack exchange,提问作者Thick_propheT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:25:10