ソートしてから任意のサイズのバッチ(たとえば、バッチごとに最大300レコード)にグループ化する必要があるレコードのCSVファイルがあります。各バッチの内容は(2つの異なる列の内容に基づいて)均等でなければならないので、各バッチは300レコード未満である可能性があります。複数のGroupByを持つバッチ
var query = (from line in EbrRecords
let EbrData = line.Split('\t')
let Location = EbrData[7]
let RepName = EbrData[4]
let AccountID = EbrData[0]
orderby Location, RepName, AccountID).
Select((data, index) => new {
Record = new EbrRecord(
AccountID = EbrData[0],
AccountName = EbrData[1],
MBSegment = EbrData[2],
RepName = EbrData[4],
Location = EbrData[7],
TsrLocation = EbrData[8]
)
,
Index = index}
).GroupBy(x => new {x.Record.Location, x.Record.RepName, batch = x.Index/100});
"/ 100" 私に任意のバケットサイズを与える:batching with LINQにこの答えに触発
私のLINQ文は、次のようになります。 groupbyの他の要素は、バッチ間の均質性を達成するためのものです。私はこれがほとんど私が欲しいと思うが、それは私に次のコンパイラエラーを与える:A query body must end with a select clause or a group clause
。私はなぜエラーを受け取っているのか理解していますが、全体的に私はこのクエリを修正する方法がわかりません。それはどうやって行なわれるのですか?
UPDATE私は非常に近く、以下に、私が後だ何を達成:
List<EbrRecord> input = new List<EbrRecord> {
new EbrRecord {Name = "Brent",Age = 20,ID = "A"},
new EbrRecord {Name = "Amy",Age = 20,ID = "B"},
new EbrRecord {Name = "Gabe",Age = 23,ID = "B"},
new EbrRecord {Name = "Noah",Age = 27,ID = "B"},
new EbrRecord {Name = "Alex",Age = 27,ID = "B"},
new EbrRecord {Name = "Stormi",Age = 27,ID = "B"},
new EbrRecord {Name = "Roger",Age = 27,ID = "B"},
new EbrRecord {Name = "Jen",Age = 27,ID = "B"},
new EbrRecord {Name = "Adrian",Age = 28,ID = "B"},
new EbrRecord {Name = "Cory",Age = 29,ID = "C"},
new EbrRecord {Name = "Bob",Age = 29,ID = "C"},
new EbrRecord {Name = "George",Age = 29,ID = "C"},
};
//look how tiny this query is, and it is very nearly the result I want!!!
int i = 0;
var result = from q in input
orderby q.Age, q.ID
group q by new { q.ID, batch = i++/3 };
foreach (var agroup in result)
{
Debug.WriteLine("ID:" + agroup.Key);
foreach (var record in agroup)
{
Debug.WriteLine(" Name:" + record.Name);
}
}
ここにトリックは閉鎖変数を使用することにより、選択し、「インデックス位置」overlaodをバイパスすることです(int i
でこの場合)。出力結果は次のとおりです。
ID:{ ID = A, batch = 0 }
Name:Brent
ID:{ ID = B, batch = 0 }
Name:Amy
Name:Gabe
ID:{ ID = B, batch = 1 }
Name:Noah
Name:Alex
Name:Stormi
ID:{ ID = B, batch = 2 }
Name:Roger
Name:Jen
Name:Adrian
ID:{ ID = C, batch = 3 }
Name:Cory
Name:Bob
Name:George
この回答は受け入れられますが、理想的な結果にはほんのわずかです。 2つではなく(Amy、Gabe、Noah)Amit、Gabeの3つのエントリーがあるはずです。これは、各グループが識別されたときにインデックスの位置がリセットされていないためです。誰もが各グループの私のカスタムインデックスの位置をリセットする方法を知っていますか?
更新2 私は答えを見つけた可能性があります。
int i = 0;
string priorID = null;
var result = from q in input
orderby q.Age, q.ID
group q by new { q.ID, batch = (BatchGroup(q.ID, ref priorID) ? i=0 : ++i)/3 };
今では私が欲しいものを行います。このようなLINQクエリを更新し、
public static bool BatchGroup(string ID, ref string priorID)
{
if (priorID != ID)
{
priorID = ID;
return true;
}
return false;
}
第二に:まず、このような追加機能を作ります。私はちょうど私がその別個の機能を必要としないことを望む!
intellisenseとコンパイラは、ドット表記に切り替わらない限り、 "select new"の後ろに "group by"を置くことを拒否します。 –
"into x"は重要です。 –
多くの厄介なタイプミスを修正しました。今私は終わった(それがうまくいくかどうか)。 –