2012-11-29 82 views
0

编辑作为问题是未回答的执行小计过滤后的数据从一个StreamReader

我已经根据1个标准滤波的输出(前3个数字是110210或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<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. 
    } 
} 

回答

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); 
      } 
     } 
    } 
} 
+0

有人可以为我赞成这个请:)我很快就会有足够的票数。 – Cylen

+0

嗨泽夫,我已经看过这个,我不明白的一件事(这也是它在输入字符串上错误输出的区域的格式不正确),是这样的: 新的 { (lineSubstring(currentLocations [2],currentLocations [3]))+ int.Parse(line.Substring())。 (currentLocations [4],currentLocations [5])) }; 为什么你使用210等的0,3,但在406 409后,为什么不是406 4等? – Cylen

+0

因为我正在使用包含一组数组的字典。 'locations [“210”]'返回一个包含所需字符位置的整数数组。第一个/第二个数字的位置在该数组内总是相同的。 –

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(); 
+0

用于LINQ和正则表达式的+1 –