0

编辑为问题未回答

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

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

示例字符串:

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 等对于相同的起始编号始终位于同一位置,但每个起始编号会有所不同。

同样,汇总金额的位置也仅在每个起始数字的相同位置。

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

// 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.
    }
}
4

2 回答 2

2
string input = File.ReadAllText("file.dat");
var result = Regex.Matches(input, "(210|310|410).*?([A-C]{3})([0-9]{5})")
    .Cast<Match>()
    .Select(m => new { 
        P1 = m.Groups[1].Value, 
        P2 = m.Groups[2].Value, 
        P3 = Convert.ToInt32(m.Groups[3].Value)
    })
    .GroupBy(x => new{x.P1,x.P2})
    .Select(x=>String.Format("{0} {1} {2}",x.Key.P1,x.Key.P2,x.Sum(y=>y.P3)))
    .ToList();
于 2012-11-29T14:31:46.703 回答
1

(在此处发布此答案,因为另一个问题已关闭。)对于大文件,使用 ReadAllText 效率低下。

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);
            }
        }
    }
}
于 2012-11-30T11:14:08.577 回答