简体   繁体   中英

How to use linq to paginate a SortedList in Ascending or Descending order

This does what I want:

if (order == SortOrder.Ascending) {
    return list.Values.Skip(pageIndex * numberPerPage).Take(numberPerPage);
} else if (order == SortOrder.Descending) {
    return list.Values.Reverse().Skip(pageIndex * numberPerPage).Take(numberPerPage);
}

However, I don't want to have to reverse the list every time this is called, I could write a for loop that goes through the list backwards and implement the paging myself, but im looking for a simple way to get this done with linq.

A couple of ideas.

  1. Reverse the list only once when they change the sorting order. Then just call the pagination normally:

     SortOrder oldOrder = SortOrder.Ascending; void SetSortOrder(SortOrder newOrder) { if(oldOrder != newOrder) { list.Values = list.Values.Reverse().ToList(); oldOrder = newOrder; } } IEnumerable<Stuff> GetPage(int pageIndex, int numberPerPage, SortOrder order) { SetSortOrder(order); return list.Values.Skip(pageIndex * numberPerPage).Take(numberPerPage); } 
  2. Keep an ascending and descending list in memory:

     List<Stuff> ascendingList, descendingList; void SetLists() { ascendingList = list.Values; descendingList = list.Values.Reverse().ToList(); } IEnumerable<Stuff> GetPage(int pageIndex, int numberPerPage, SortOrder order) { return (order == SortOrder.Ascending ? ascendingList : descendingList).Skip(pageIndex * numberPerPage).Take(numberPerPage); } 

In addition to storing the "sorted" list (calling Reverse really just creates a backwards iterator, it doesn't re-sort). You don't have to use Skip if you don't want to.

For example, if you are always showing Page 1, then Page 2, then page 3, you can simply use Take alone:

// done when user clicks something to change `order`
orderedEnumerator = order == SortOrder.Ascending ? list : list.Reverse();
//...
foreach(var e in orderedEnumerator.Take(pageSize)
{
// show first page
}
foreach(var e in orderedEnumerator.Take(pageSize)
{
// show second page
}
foreach(var e in orderedEnumerator.Take(pageSize)
{
// show third page
}

The actual foreach code could be the same block of code simply executed at different times, eg:

IEnumerable<MyType> GetCurrentPage()
{
    return orderedEnumerator.Take(pageSize);
}

public void nextPageButton_Click(object sender, EventArgs e)
{
   foreach(var e in GetCurrentPage())
   {
      // elements in current page
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM