对来自流阅读器的过滤数据执行小计 [英] Performing a subtotal on filtered data from a streamreader

查看:24
本文介绍了对来自流阅读器的过滤数据执行小计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑为未回答的问题

我有一个基于 1 个条件的过滤输出(前 3 个数字是 110,210 或 310,以提供 3 个不同的组)到来自流阅读器的控制台.问题已编辑,因为第一个答案是我给出的具体示例的字面解决方案,我使用的实际字符串长度为 450 个 ASCII 字符.我已经调整了示例字符串来解决这个问题,任何适用于示例数据的东西都适用于我所拥有的.

I have a filtered output based on 1 criteria (first 3 numbers are 110,210 or 310,to give 3 distinct groups) to console from streamreader. Question edited because first answer was a literal solution to the specific example I gave, the real strings I'm using are 450 ASCII characters long. I have adjusted the example strings to remedy this, anything that works on the sample data will work on what I have.

所以我真正需要的是可以根据前 3 个数字从预先指定的已知位置中取出 3 个字母的东西(对于 210,它将是字符槽 14-16,然后将其用作子类别,总和字符槽 33-37 中的所有条目,并输出那些).

so what i really need is something that can, depending on the first 3 numbers, take the 3 letters from a predesignated known location (for 210's it'll be character slot 14-16 and then using that as a subcategory, sum up all entries in character slot 33-37, and output those).

示例字符串:

210!!!!123244AAA75AWEHUIHJUAS!!!11111
210???1223455ABC76554HJHSDFQ????22222
210--32455623ABCFFCDGHDSFAS-----33333
310         1232451    2ABC34       GAERsASDFASDG1234523   44444
310 1234a354GDSAASDR  3 AAA  GF234523653hfdssdgSDASDF      11111
310 12378HJK1234        ABC HJHJK123462 ASDHDFS FA REW     22222
4101111ASDJF     1ABCASF        D1234    ASGF66666
4102222QW12362ER2 ABC 23459876HJKXC          11111
41033333T123 1RWE AAA  ASDFHJKRTR  WQ        22222

最后,我的输出是:

210 AAA 11111
210 ABC 55555
310 ABC 66666
310 AAA 11111
410 ABC 77777
410 AAA 22222

ABC、AAA 等对于相同的起始号码总是在相同的位置,但每个起始号码会有所不同.

The ABC, AAA etc. are always in the same location for the same starting number, but will be different per starting number.

同样,相加金额的位置也仅在每个起始数字的相同位置.

Likewise the location of the amounts being summed up are also only in the same place per each starting number.

我尝试在现有代码中添加一些 string.split(如下),但没有任何运气.

I've tried adding some string.split to the existing code (below) but haven't had any luck.

// Read in a file line-by-line, and store in a List.
List<string> list = new List<string>();
using (StreamReader reader = new StreamReader("file.dat"))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        var beginning = line.Substring(0, 3);
        if (beginning != "210" && beginning != "310" && beginning != "410")
            continue;
        list.Add(line); // Add to list.
        Console.WriteLine(line); // Write to console.
    }
}

推荐答案

(在此发布此答案,因为其他问题已关闭.)对于大文件,使用 ReadAllText 效率低下.

(Posting this answer here, as the other question is closed.) Using ReadAllText will be inefficient for large files.

public static class LinqToTextReader {
    public static IEnumerable<string> AsEnumerable(this TextReader reader) {
        string line;
        while ((line = reader.ReadLine()) != null) {
            yield return line;
        }
    }
}

class Program {
    static void Main(string[] args) {
        using (StreamReader reader = new StreamReader("file.dat")) {
            var locations = new Dictionary<string, int[]>() {
                {"210", new [] {406, 409, 129, 140, 142, 153}},
                {"310", new [] {322, 325, 113, 124, 126, 137}},
                {"410", new [] {478, 481, 113, 124, 126, 137}}
            };

            var query =
                from line in reader.AsEnumerable()
                let lineStart = line.Substring(0, 3)
                where lineStart == "210" || lineStart == "310" || lineStart == "410"
                let currentLocations = locations[lineStart]
                select new {
                    letters = line.Substring(currentLocations[0], currentLocations[1]),
                    value =
                        int.Parse(line.Substring(currentLocations[2], currentLocations[3])) +
                        int.Parse(line.Substring(currentLocations[4], currentLocations[5]))
                };

            //It should be possible to combine the two queries
            var query2 = 
                from item in query
                group item by item.letters into letterGroup
                select new {
                    letters = letterGroup.Key,
                    total = letterGroup.Sum(item => item.value)
                };

            foreach (var item in query2) {
                Console.WriteLine(item.letters);
                Console.WriteLine(item.total);
            }
        }
    }
}

这篇关于对来自流阅读器的过滤数据执行小计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆