0

パイプで区切られた非常に大きなファイル (> 1GB) があります。file.readlines を使用してファイルをクエリし、各行を分割し、インデックス リスト (インデックスの配列を提供します) に従って、分割された行から特定の要素を選択し、それをカスタム型クラス オブジェクトのディクショナリに返します。

現在、私はこれを持っています:

strIndexes = "1,3,5,7";
var selected = strIndexes.Split(',')
                         .Select(x => int.Parse(x))
                         .Select(index => File.readlines(myFile)
                         .Select(x => split('|')[index]).toArray();

ただし、このクエリはインデックスによって導かれるため、それほど効率的ではありません。上記の例で指定された 4 つのインデックスにそれぞれ対応する 4 つのベクトルを返します。

助けていただければ幸いです。

アップデート:

コメントありがとうございます。サンプルデータを追加しています。ファイル データは次のようになります。

Line1: aa|ab|de|gt|hj|de|fr|gt|hy // Header
Line2: sd|12|f4|tr|hj|df|ds|e3|12
Line3: 34|fd|3d|35|df|45|dq|32|dd
.
.
.
Line N 34|df|f3|df|33|s2|23|df|44

N = 数百万行。データ形式は例のためのものであり、各セルは異なる長さと構造の文字列を保持しています。

ここで、ユーザーは要求されたデータをヘッダー列名の形式で入力します。たとえば、ab、de、fr、hy とします。これを解析し、列 2、3、7、および 9 が必要であることを理解しました。ファイルを解析し、各エントリが辞書エントリであるオブジェクトを返します。これは、行内のデータを表し、キー (列データの 1 つ) とトークン化されたデータの文字列 [] である値を保持します。

したがって、この例では、データを列番号 7 で並べ替えたいので、最終的な辞書は次のようになります。

[ds]->[12,f4,12]
[dq]->[fd,3d,dd]
.
.
.
[23]->[df,f3,44]
4

4 に答える 4

0

あなたはlinqソリューションを求めましたが、ファイルが大きく、単一のタスクに多くのメモリを割り当てたり、OutOfMemoryExceptionを取得したりするため、これはおそらく良い習慣ではないと思います.

ファイルの各行を一度解析して、各インデックスの値を抽出できます。

public Dictionary<int, List<String>> ParseFile(String fileName, int[] indexes)
    var file = File.OpenText(myFile);
    var dict = indexes.ToDictionary(i => i, i => new List<string>());

    while(!file.EndOfStream)
    {
        var line = file.ReadLine().Split('|');
        foreach(var entry in dict)
            entry.Value.Add(line[entry.Key]);
    }
    file.Dispose();
    return dict;
}
于 2012-08-01T21:25:55.177 に答える
0

最初に、クエリの外部でインデックス文字列 (strIndex) を解析して、その手順を複数回繰り返さないようにします。

string strIndexes = "7,2,3,9";
int[] indexes = Array.ConvertAll(strIndexes.Split(','), e => int.Parse(e) - 1);

最初のインデックスがキー インデックスであると仮定すると、必要なコードが単純化されるため、最初に 7 を配置したことに注意してください。また、インデックスが文字列内で 1 から始まるように見えることにも気付きました。そのため、1 を引いて 0 から始まるインデックスの配列を作成します。次に、これにより、Dictionary<string, string[]>要求したフォームの が生成されます。

var selected = (from line in File.ReadLines(myFile)
                let lineArray = line.Split('|')
                select (from index in indexes
                select lineArray[index]))
               .ToDictionary(key => key.First(), value => value.Skip(1).ToArray());

これを 4 行のサンプル データに対して実行すると、次の結果が得られます。

[fr]->[ab, de, hy]
[ds]->[12, f4, 12]
[dq]->[fd, 3d, dd]
[23]->[df, f3, 44]

このコードから:

foreach (var item in selected)
{
    Console.WriteLine("[{0}]->[{1}]", item.Key, string.Join(", ", item.Value));
}
于 2012-08-01T21:02:54.960 に答える
0

いくつかの推測ですが、おそらくこれがあなたのやりたいことです:

// Split indexes string to integers
var indexes = strIndexes.Split(',').Select(int.Parse);

// Read file once
var lines = File.ReadLines(myFile);

// Split them (thank you, devundef!)
var splitLines = lines.Select(line => line.Split('|')).ToArray();

// Create dictionary index => column array
var dict = indexes.ToDictionary(
        index => index,
        index => splitLines.Select(splitLine => splitLine[index]).ToArray()
    );
于 2012-08-01T20:42:42.370 に答える
0

独自のトークナイザーを作成する (または見つける) ことをお勧めします。String.IndexOfAnyを使用して、「|」を検索できます。または「、」、独自のステートマシンを構築して、これらの値をどこにプロットするかを伝えます。

于 2012-08-01T20:31:18.033 に答える