我有一个文本文件.我需要找到行号的总计数,以"3"开始,总计数已经在文件中可用,该文件在以"7200"开始的位置行中可用-位置以05开始,长度为6.类似的方式.行中可用的总金额从"7200"开始-位置从21开始,长度为12.

.txt File Data

211 87236486287346872837468724682871238483XYZ BANK             
1200ABCDEF                               8128361287AXTAKJ COLL
3270210000893281012870095628   00002500     8981273687jhgsjhdg

3270210000896281712870095628   00002500     1231273687jhgajhdj

3270210000891286712870095628   00002500     4561273687cxvnmbal

3270210000899283612870095628   00002500     7891273687nmkdkjhk

720000000400021000080000000100000000000000008128361287        
9000001000001000000010002100008000000010000000000000000       

例如:在我的文件中,以3开头的行的总数在以"7"开头的行中可用,即"000004"

总金额以"7"开头,即"0000000 10000"

目前,我正在使用下面的c代码来循环整个文件,并导航到以7开头的行,并读取上述位置中可用的值,但由于文件记录数可能太大(如200K),需要花费太多时间

foreach (var line in FileLines)
{
    //// If line length is zero, then do nothing
    if (line.Length == 0)
    {
        continue;
    }

    switch (line.Substring(1, 1))
    {
        case 7:
            totalCount = int.Parse(line.Substring(4, 6));
            TotalAmount = line.Substring(20, 12);
            break;

        default:
            throw new Exception;
    }
}

有什么方法可以使用LINQ重写代码,从而获得更好的性能?

推荐答案

这是Linq声明.更有效的是,它使用Reverse,因为您提到您要查找的信息在页脚中.

static void Main(string[] args)
{
    var path = Path.Combine(
        Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
        "TextFile.txt");
    try
    {
        var count =
            int.Parse(
            File.ReadAllLines(path)
            .Reverse()
            .First(line => line.Any() && (line.First() == '7'))
            .Substring(4, 6));
        Console.WriteLine($"Count = {count}");
    }
    catch (Exception ex)
    {
         System.Diagnostics.Debug.Assert(false, ex.Message);
    }
}

console output

EDIT

你问了一个关于表演的好问题.最棒的是,我们不必猜测!有always种方法可以衡量绩效.

这是我刚刚制定的基准.看,我做得很快,所以如果有人发现我遗漏了什么,请指出.但我得到的是:

static void Main(string[] args)
{
    var path = Path.Combine(
        Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
        "TextFile.txt");
    try
    {
        // 200K lines of random guids
        List<string> builder = 
            Enumerable.Range(0, 200000)
            .Select(n => $"{{{System.Guid.NewGuid().ToString()}}}")
            .ToList();

        var footer =
            File.ReadAllLines(path);

        builder.AddRange(footer);

        var FileLines = builder.ToArray();

        var benchmark = new System.Diagnostics.Stopwatch();
        benchmark.Start();
        int totalCount = int.MinValue;
        foreach (var line in FileLines)
        {
            //// If line length is zero, then do nothing
            if (line.Length == 0)
            {
                continue;
            }
            // Original code from post
            // switch (line.Substring(1, 1))
            // Should be:
            switch (line.Substring(0, 1))
            {
                case "7":
                    totalCount = int.Parse(line.Substring(4, 6));
                    // This is another issue!! Breaking from the switch DOESN'T break from the loop
                    break;
                    // SHOULD BE: goto breakFromInner;
                    // One of the few good reasons to use a goto statement!!
            }
        }
        benchmark.Stop();
        Console.WriteLine($"200K lines using Original code: Elapsed = {benchmark.Elapsed}");
        Console.WriteLine($"Count = {totalCount}");


        benchmark.Restart();
        for (int i = FileLines.Length - 1; i >= 0; i--)
        {
            var line = FileLines[i];
            //// If line length is zero, then do nothing
            if (line.Length == 0)
            {
                continue;
            }
            // Original code from post
            // switch (line.Substring(1, 1))
            // Should be:
            switch (line.Substring(0, 1))
            {
                case "7":
                    totalCount = int.Parse(line.Substring(4, 6));
                    // One of the few good reasons to use a goto statement!!
                    goto breakFromInner;
            }
        }
        // See note
        breakFromInner:
        benchmark.Stop();
        Console.WriteLine($"200K lines using Original code with reverse: Elapsed = {benchmark.Elapsed}");
        Console.WriteLine($"Count = {totalCount}");

        benchmark.Restart();
        var count =
            int.Parse(
                FileLines
                .Reverse()
                .First(line => line.Any() && (line.First() == '7'))
                .Substring(4, 6));
        benchmark.Stop();
        Console.WriteLine($"200K lines using Linq with Reverse: Elapsed = {benchmark.Elapsed}");
        Console.WriteLine($"Count = {count}");
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.Assert(false, ex.Message);
    }
}

console output

Csharp相关问答推荐

当打印一行x个项目时,如何打印最后一行项目?

无法从具有一对多关系的C#类中使用Swagger创建记录

获取ASP.NET核心身份认证cookie名称

将委托传递到serviceccollection c#web API

编写DataAnnotations自定义验证器的多种方法

如何注销Microsoft帐户?

MigraDoc文档

共享暂存/生产环境中Azure事件中心的建议配置

TeamsBot SendActivityActivityTypes与ActivityTypes同步.键入不再起作用

在C#中,将两个哈希集连接在一起的时间复杂度是多少?

如何在C#中转换泛型包装类内部的派生类

在C#中,当输入一个方法/局部函数时,我的IEnumerator被重置/重新创建.为什么?

VS代码扩展无法在新版本扩展C#中运行从v2.10.28开始

如何从SignalR获取连接客户端的域

如何使用LINQ在C#中填充列表列表?

使用免费的DotNet库从Azure函数向Azure文件共享上的现有Excel文件追加行

S,在.NET核心控制台应用程序中,AddScope和AddSingleton有什么不同?

无法对包含字符串的列进行排序.请与实体框架联接

微服务之间的通信是使用API调用还是仅使用Message Broker?

为什么LoadLibrary无法加载由vcpkg构建的OpenCV_world DLL,而不是预构建的二进制版本?