I want to implement paging on a list of data. The list has some fake items in itself as flag items for doing some specific work on the data. A simplified version of what I have done is as below:
List<Model> list = _myServiceContract.MyServiceMethod(MySearchModel);
pagedData = list.Skip((page - 1) * pageSize).Take(pageSize);
But my problem with this way is that the fake items will be counted in the Skip
and Take
methods of the Linq.
I want to know if it is possible to ignore those fake items in the Skip
method then apply Skip
on the list, including fake items by some changes in the Take
method for example or something similar.
Edit: The first list is ordered before doing paging and those fake items are in ordered places also. You should know the order of the list is important for me.
The Take operator is used to return a given number of elements from an array and the Skip operator skips over a specified number of elements from an array. Skip, skips elements up to a specified position starting from the first element in a sequence.
Skip specifies a number of items to skip. SkipWhile allows you to supply a predicate function to determine how many to skip.
Use the Skip() method in C# to skip number of elements in an array.
To be honest I don't like what you're doing. I'd consider modelling your data better in future. However, here's a couple of extension methods that'll get the job done...
(I've essentially modified the original implementations of Skip
and Take
from https://github.com/Microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs)
public static IEnumerable<TSource> SkipAndInclude<TSource>(this IEnumerable<TSource> source, int count, Func<TSource, bool> predicate)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (predicate == null) throw new ArgumentNullException(nameof(predicate));
using (IEnumerator<TSource> e = source.GetEnumerator())
{
while (count > 0 && e.MoveNext())
{
if (!predicate(e.Current)) count--;
}
if (count <= 0)
{
while (e.MoveNext()) yield return e.Current;
}
}
}
public static IEnumerable<TSource> TakeAndInclude<TSource>(this IEnumerable<TSource> source, int count, Func<TSource, bool> predicate)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (predicate == null) throw new ArgumentNullException(nameof(predicate));
if (count > 0)
{
foreach (TSource element in source)
{
yield return element;
if (!predicate(element)) count--;
if (count == 0) break;
}
}
}
Usage...
pagedData = list.SkipAndInclude((page - 1) * pageSize, x => x.Fake).TakeAndInclude(pageSize, x => x.Fake);
How about iterating over the list manually to find the index of fake items, then adding them in later. Something like this:
var fakeItems = new Dictionary<int, Model>();
var unpaged = MyService.MyServiceMethod(MySearchModel);
for (var i = 0; i < unpaged.Count; i++)
{
if (unpaged[i].IsFake)
fakeItems.Add(i, unpaged[i]);
}
var paged = unpaged.Where(x => !x.IsFake)
.Skip((page - 1) * pageSize)
.Take(pageSize);
foreach (var item in fakeItems){
{
if((pageSize * (page - 1)) <= item.Key && item.Key < (pageSize * page))
paged.Insert(item.Key, item.Value);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With