5

只是在寻找对此的一些确认。我需要为我的列表捕获上一个和下一个 ID。有没有更好的办法?

var questionArray = dc.Question
    .Where(i => !i.IsDeleted)
    .OrderBy(i => i.SortOrder)
    .Select(i => new
    {
        i.QuestionID,
        i.Name,
    })
    .ToArray();

var questionList = questionArray
    .Select((item, index) => new
    {
        item.QuestionID,
        PrevID = index > 0 ? questionArray[index - 1].QuestionID : (int?)null,
        NextID = index < questionArray.Length - 1 ? questionArray[index + 1].QuestionID : (int?)null,
        item.Name,
    })
    .ToList();
4

2 回答 2

6

您可以编写一个小助手扩展来消除对结果数组的需要

public static IEnumerable<TResult> PrevNextZip<T, TResult>(this IEnumerable<T> stream, Func<T, T, T, TResult> selector) where T : class
{
  using (var enumerator = stream.GetEnumerator())
  { 
    if (enumerator.MoveNext())
    {
      T prev = null;
      T curr = enumerator.Current;

      while (enumerator.MoveNext())
      {
        var next = enumerator.Current;
        yield return selector(prev, curr, next);
        prev = curr;
        curr = next;
      }

      yield return selector(prev, curr, null);
    }
  }
} 

然后构建您的结果将如下所示

  var questionList = questionArray.PrevNextZip((prev, item, next) => new
    {
      item.QuestionID,
      PrevID = prev != null ? prev.QuestionID : (int?)null,
      NextID = next != null ? next.QuestionID : (int?)null,
      item.Name,
    })
    .ToList();
于 2012-10-07T17:54:00.237 回答
0

您可以使用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 ();
于 2012-10-07T17:27:14.967 回答