是否可以使用 LINQ 的 Skip 方法忽略列表项,然后在列表上应用 skip 而不会丢失该项目?
Posted
技术标签:
【中文标题】是否可以使用 LINQ 的 Skip 方法忽略列表项,然后在列表上应用 skip 而不会丢失该项目?【英文标题】:Is it possible to ignore a list item using the Skip method of the LINQ then apply skip on the list without losing that item? 【发布时间】:2018-05-05 00:24:53 【问题描述】:我想在数据列表上实现分页。该列表本身有一些虚假项目作为标记项目,用于对数据进行某些特定工作。我所做的简化版本如下:
List<Model> list = _myServiceContract.MyServiceMethod(MySearchModel);
pagedData = list.Skip((page - 1) * pageSize).Take(pageSize);
但我对这种方式的问题是,假货将计入 Linq 的 Skip
和 Take
方法中。
我想知道是否可以忽略Skip
方法中的那些假项目,然后在列表中应用Skip
,包括通过Take
方法或类似方法中的一些更改而产生的假项目。
编辑:第一个列表是在进行分页之前排序的,那些假项目也在有序的地方。你应该知道列表的顺序对我很重要。
【问题讨论】:
您可以在Skip
前面加上Where
以首先过滤掉“假”物品。
没有@juharr。条件会从结果中丢失假数据
你能TakeWhile(fake).Skip((page - 1) * pageSize).Take(pageSize)
吗?一组示例数据会很有帮助,我不太确定从您的描述中会是什么样子。
类似.SkipWhile(x => (x.IsFake ? toSkip : toSkip--) > 0).TakeWhile(x => (x.IsFake ? toTake : toTake--) > 0)
。您只需预先计算 toSkip
和 toTake
并允许查询在您检查项目是否为假时改变这些值。
【参考方案1】:
说实话,我不喜欢你的所作所为。我会考虑将来更好地对您的数据进行建模。但是,这里有几个扩展方法可以完成工作......
(我从https://github.com/Microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs 基本上修改了Skip
和Take
的原始实现)
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;
用法...
pagedData = list.SkipAndInclude((page - 1) * pageSize, x => x.Fake).TakeAndInclude(pageSize, x => x.Fake);
【讨论】:
【参考方案2】:如何手动遍历列表以查找虚假项目的索引,然后稍后添加它们。像这样的:
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);
【讨论】:
【参考方案3】:只需使用 where 来忽略这些项目,如下所示:
List<Model> list = MyService.MyServiceMethod(MySearchModel);
pagedData = list.Where(x => !x.Fake).Skip((page - 1) * pageSize).Take(pageSize).ToList();
不要忘记订购您的物品。否则在分页(skip & take)时可能会出现问题。
【讨论】:
我之前试过这个解决方案。它将从结果中丢失假货。 我不完全明白你想在哪里拥有这些物品以及每页应该有多少假货。在我看来,也许你正试图用一个 List 做一些你应该用两种不同的方法做的事情?请向我提供有关您的要求的更多信息,以便我想出更好的解决方案。以上是关于是否可以使用 LINQ 的 Skip 方法忽略列表项,然后在列表上应用 skip 而不会丢失该项目?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Linq Skip Take 进行传统 SQL 查询,而不是使用 RowNum
PagedList 使用 LINQ Skip and Take,但使用 Count of results 显示分页
分页错误:仅 LINQ to Entities 中的排序输入支持“跳过”方法。方法 'OrderBy' 必须在方法 'Skip' 之前调用