Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IEnumerable with Prev/Next

Tags:

c#

linq

Just looking for some confirmation on this. I need to capture the previous and next IDs for my list. Is there a better way?

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();
like image 512
andleer Avatar asked Oct 07 '12 17:10

andleer


1 Answers

You could write a little helper extension to remove the need to have an array of results

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);
    }
  }
} 

Then building your result would look like this

  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();
like image 181
MerickOWA Avatar answered Sep 27 '22 22:09

MerickOWA