非常に慣れていない生データフォーマットを圧縮する必要があるのは、特定の部分を抽出してLUTとはるかに短いデータライン。regex/linqの2GBメモリフットプリントを減らすか、そうでなければdistinct group値を取得する
私のテストデータは、約400k行を含むファイルから読み込まれます。私はデータを作成するためのプログラム的な方法で書きました。
今のところ、私は主に出力するグループの異なる値に興味があります。 'ref'と 'ref2'も必要ですが、それ自体はほとんどユニークです。
regexを介した 'naive' aproachは動作しますが、2GB以上のプロセスメモリと多くの時間を要します。正規表現を最適化する方法とは別の方法で別の値を取得する方法はありますか?
編集:Wiktor Stribiżewヒントのおかげで700MBまで編集できます。
using System;
using System.Linq;
using System.Text.RegularExpressions;
TESTDATA /制作:
static string[] NAMES1 = "cat,dog,deer,buffalo,lion,mouse,hedgehog".Split(',');
static string[] NAMES2 = "lily,rose,thyme,salt".Split(',');
static string[] TYPES = "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2".Split(',');
static string MakeText (int n, string[] names)
{
if (n % 15 == 0)
return $"{names[n % names.Length]}${n}";
else if (n % 5 == 0)
return $"{names[n % names.Length]}${n}${TYPES[n % TYPES.Length]}";
else
return $"{names[n % names.Length]}$EGAL${n}${TYPES[n % TYPES.Length]}$MORE";
}
static string CreateData (int rows)
{
var ids = Enumerable.Range(0,8).Select(n => $"{Guid.NewGuid()}-1234").ToList();
var id2 = $"{Guid.NewGuid()}-9876";
Console.WriteLine ($"\nIDs: {string.Join ("\n ", ids)}");
Console.WriteLine ($"\nID 2: {id2}");
Console.WriteLine ($"\nNAMES1: {string.Join (", ", NAMES1)}");
Console.WriteLine ($"\nNAMES2: {string.Join (", ", NAMES2)}");
var inOrder =
Enumerable
.Range(0, rows/2)
.Select(n => $"{MakeText(n,NAMES1)}," +
$"{ids[ Math.Min(ids.Count-1,n/(rows/2/ids.Count))]}" +
$"={MakeText(Math.Min(int.MaxValue,rows*10)-n,NAMES2)},{id2}");
var outOfOrder =
Enumerable
.Range(rows/2, rows)
.Select(n => $"{MakeText(n,NAMES1)},{ids[n % ids.Count]}" +
$"={MakeText(int.MaxValue-n,NAMES2)},{id2}");
return string.Join (Environment.NewLine, inOrder.Concat (outOfOrder))
+ Environment.NewLine;
}
正規表現の使用:
static void Main (string[] args)
{
var content= CreateData (400000);
var r = new Regex(
@"^(?<ar>.+?)(\$EGAL)?(\$(?<ref>[0-9]+))(\$(?<typ>[123]))?" +
@"(\$MORE)?(,(?<id>.+))"+
@"=(?<ar2>.+?)(\$EGAL)?(\$(?<ref2>[0-9]+))(\$(?<typ2>[123]))?" +
@"(\$MORE)?(,(?<id2>.+))(\r)?$",
RegexOptions.Compiled|RegexOptions.Multiline|RegexOptions.ExplicitCapture);
var matches = r.Matches(content).OfType<Match>().ToList();
var ids1 = matches
.Select(
m => m
.Groups["id"]
.Captures
.OfType<Capture>()
.Select(c=> c.Value)
)
.SelectMany(i=>i)
.Distinct()
.ToList();
Console.WriteLine ($"\nids: {string.Join ("\n ", ids1)}");
var ids2 = matches
.Select(
m => m
.Groups["id2"]
.Captures
.OfType<Capture>()
.Select(c=> c.Value)
)
.SelectMany(i=>i)
.Distinct()
.ToList();
Console.WriteLine ($"\nid 2: {string.Join ("\n ", ids2)}");
var n1 = matches
.Select(
m => m
.Groups["ar"]
.Captures
.OfType<Capture>()
.Select(c=> c.Value)
)
.SelectMany(i=>i)
.Distinct()
.ToList();
Console.WriteLine ($"\nnames1: {string.Join (", ", n1)}");
var n2 = matches
.Select(
m => m
.Groups["ar2"]
.Captures
.OfType<Capture>()
.Select(c=> c.Value)
)
.SelectMany(i=>i)
.Distinct()
.ToList();
Console.WriteLine ($"\nnames2: {string.Join (", ", n2)}");
// need the type's and refs as well to recreate the substituted
// datalines after creating the LUT and put them together in some
// new file - that's easy.
}
パターンを正確にすると、[適切なサブパターンで '.'を置き換えます](https://regex101.com/r/knSux2/1 )、あなたは大幅に正規表現のパフォーマンスを向上させることができます。また、 'Regex.Matches'を一度実行し、結果を変数に格納し、キャプチャコレクションにアクセスするときに再利用します。 –
Regex.Matchesを2GBから700MBに減らしてくれてありがとう、Wiktorに感謝します。私はサブパターンを調べます。 –
パターンの最適化では、テストの内容には可能なすべてのバリエーションの種類が含まれていないようです。主なポイントは、このようなシナリオでの主要なパフォーマンス・キラーである '。+? 'よりも制限されたパターンを探しています。 –