0

質問に回答がない場合は編集

ストリームリーダーからコンソールへの1つの基準(最初の3つの数値は110、210、または310で、3つの異なるグループを提供)に基づいてフィルター処理された出力があります。最初の答えは私が与えた特定の例の文字通りの解決策だったので、質問を編集しました。私が使用している実際の文字列は、450ASCII文字の長さです。これを修正するためにサンプル文字列を調整しました。サンプルデータで機能するものはすべて、私が持っているものでも機能します。

したがって、私が本当に必要としているのは、最初の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 に答える