对来自流读取器的过滤数据执行小计

编辑为问题没有答案

我有一个基于1个标准的过滤输出(前3个数字是110,210或310,给3个不同的组)来自streamreader的控制台。 问题编辑,因为第一个答案是我给出的具体例子的文字解决方案,我使用的真正字符串是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 list = new List(); 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对于大文件来说效率低下。

 public static class LinqToTextReader { public static IEnumerable 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() { {"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); } } } } 
 string input = File.ReadAllText("file.dat"); var result = Regex.Matches(input, "(210|310|410).*?([AC]{3})([0-9]{5})") .Cast() .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();