编辑为问题未答复
我有一个基于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<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.
}
}
答案 0 :(得分: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();
答案 1 :(得分: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);
}
}
}
}