2016-11-25 12 views
0

これが私のデータであり、行と列を表し、データのサイズがInt.MaxValue(はい、非常に大きい)とします。LINQ大規模なデータ操作。メモリ不足例外

ですから、例えば、これは、それがどのように見えるかです:

10, "Twenty", 30, 40, 21/08/2016 00:00:00 
10, "Twenty", 30, 40, 21/08/2016 00:00:00 
10, "Twenty", 30, 40, 21/08/2016 00:00:00 
10, "Twenty", 30, 40, 21/08/2016 00:00:00 
10, "Twenty", 30, 40, 21/08/2016 00:00:00 
..repeated int.maxvalue times. 

[OK]を、我々は5列とint.maxvalue行がある見ることができるように。

私がしたいことは、各列にロジックを適用することです。それでは言わせて:

列1つのロジック=「NoRepeat」(のみ、この欄の1つの値が存在すべきであることを意味)

列2ロジック=「ユニーク」(唯一のこの列の一意の値があるはずです意味します)

列3ロジック=「無効」

列4及び5ロジック=「デフォルト」(そのまま手段がそれを残す)(この列には値があってはならない手段)。

SO最後に、これは期待される結果のようになります。

10, "Twenty", "", 40, 21/08/2016 00:00:00 
"", "",  "", 40, 21/08/2016 00:00:00 
"", "",  "", 40, 21/08/2016 00:00:00 
"", "",  "", 40, 21/08/2016 00:00:00 
"", "",  "", 40, 21/08/2016 00:00:00 

私はこの使用してLINQを行うために管理が、10万行、それはメモリ不足の例外スローの前に、私が操作できる限り多くのです。

誰かが私を助けてくれますか?

これは私が持っている現在の実装である:

var group = data.SelectMany(x => x.Select((InnerValue, Index) => new { Index, InnerValue })).GroupBy(x => x.Index).Select(x => 
      { 
       string logicType = logics.ElementAt(x.First().Index); 

       switch (logicType) 
       { 
        case "NoRepeat": 
         return x.Select((OuterValue, Index) => new { Index, OuterValue }).Select(y => 
          { 
           return y.Index == 0 ? y.OuterValue.InnerValue : string.Empty; 
          }); 
        case "Unique": 
         return x; 
        case "Disabled": 
         return x; 
        default: 
         return x; 
       } 
      }).SelectMany(x => x.Select((Value, Index) => new { Index, Value })).GroupBy(x => x.Index).Select(x => x.Select(y => y.Value)); 
+3

'OutOfmemoryException'を引き起こすコードは表示されていません。遅延実行を使用しているため、' Enumerable.Repeat'ではありません。リストを満たす 'ToList'や' foreach'を使ったことがあります。もちろん、あなたは無限に記憶を埋めることはできません。たとえば、結果をファイルやデータベースに書き込むなど、別の方法で処理する必要があります([バッチ処理](https://en.wikipedia.org/wiki/Batch_processing)または1行の後にもう一方)。 –

+0

彼は 'IEnumerable'を取得しています。オブジェクトは' .ToList() 'のようなものを呼び出すまで存在しないので、Int、String(6文字)、int、in、datetime(long i believe)オブジェクトを持ち、2.1億これらのオブジェクトの。 (32,6x16,32,32,64)の合計224ビットまたは28バイトのビットフットプリントを簡単に計算できます。 2,147,483,647回、これは55.9ギガヘルツです。 – Franck

+0

@TimSchmelter私は現在の実装で投稿を編集しました。 –

答えて

0

は、これをしてください試してみてください。

この例では、マシン上で実行するとわずか数メガバイトのメモリしか消費しません。

IEnumerable<IEnumerable<object>> data = Enumerable.Repeat(new List<object> { 10, "Twenty", 30, 40, DateTime.UtcNow }, int.MaxValue); 

var hashSet = new HashSet<string>(); 

var result = data.Select((enumerable, index) => 
{ 
    var list = (List<object>)enumerable; 

    if (index > 0) list[0] = null; // only 1 value 

    // unique 
    string str = (string)list[1]; 
    if (hashSet.Contains(str)) 
     list[1] = null; 
    else 
     hashSet.Add(str); 

    list[2] = null; // disabled 

    return list; 
}); 

Console.WriteLine(result.Count()); 

「1値のみ」と「無効」のロジックは、メモリをまったく消費しません。

「ユニーク」のロジックを実装するために、私はHashSetを使用しました。ユニークな要素の数に比例してメモリを消費します。ユニークな要素の数が少ない場合、すべて正常に動作します。ユニークな要素の数が多い場合(何もする必要はありません)、メモリ消費量は大きくなります。