を使用してリストを作成できますAggregate
。構築する集約は、次の要素に設定するための最後の要素を追跡し、新しい要素が挿入されるとすぐに最後の要素をPrevID
更新します。NextID
このようなことについて:
class Info { ... // QuestionID, PrevID, NextID, Name }
class ListBuilder { List<Info> list; Info lastElement; }
var questionList = dc.Question
.Where(i => !i.IsDeleted)
.OrderBy(i => i.SortOrder)
.Aggregate (
new ListBuilder () { list = new List<Info> (), lastElement = null },
(acc, source) => {
var lastElement = acc.lastElement;
var newElement = new Info () {
QuestionID = source.QuestionID,
PrevID = lastElement != null ? lastElement.QuestionID : null,
NextID = null
};
acc.list.Add (newElement);
if (lastElement != null) lastElement.NextID = source.QuestionID;
acc.lastElement = newElement;
return acc;
})
.list;
これにより、関数型プログラミングの「精神」が保持されますが、単純にクロージャーを使用して、linq クエリの直前に定義されたローカル変数で必要な情報を追跡することもできます。
または、そのための関数を構築します。
IEnumerable<Info> previousNextInfo (IEnumerable<QuestionType> sourceEnumerable) {
Info preprevious = null;
Info previous = null;
Info current = null;
foreach (Info newOne in sourceEnumerable) {
preprevious = previous;
previous = current;
current = newOne;
yield return new Info () {
QuestionID = previous.ID,
lastID = preprevious != null ? preprevious.ID : null,
nextID = current.ID
};
}
if (current != null)
yield return new Info () { QuestionID = current.ID, lastID = previous.ID, nextID = null };
}
...
questionList = previousNextInfo (dc.Question
.Where(i => !i.IsDeleted)
.OrderBy(i => i.SortOrder)
).ToList ();