也许我在问一些废话,但我不明白如何构建LINQ查询,如果第三方方法需要参数limitoffset,并返回totalitems.

到目前为止我所做的是:

Enumerable.
Range(0, maxPages /*1000*/).
Select(i => i * maxLimit /*96*/).
Select(offset => new {
    offset = offset,
    result = api3.SearchQuery(searchTerm, maxLimit, offset)
}).
TakeWhile(a => a.offset <= a.result.total).
SelectMany(a => a.result.items).
ToArray()

显然,这个查询额外调用了一个api3.SearchQuery(结果将是result.items.Length == 0,所以理论上a.offset <= a.result.total可以用a.result.items.Length > 0替换).

有没有办法消除多余的电话?

推荐答案

你是对的,理论上a.offset <= a.result.total可以用a.result.items.Length > 0代替,但有一个问题.

TakeWhile在生成元素之前判断谓词.这意味着即使你知道没有更多的结果,它也会做一个额外的提取.

获得所需精确控制的一种方法是定义一个自定义的TakeUntil方法,比如这个方法,它很大程度上受到了MoreLinq的启发.

public static class EnumerableExtensions
{
    public static IEnumerable<TSource> TakeUntil<TSource>(
        this IEnumerable<TSource> source,
        Func<TSource, bool> predicate)
    {
        ArgumentNullException.ThrowIfNull(source);
        ArgumentNullException.ThrowIfNull(predicate);

        return _(); IEnumerable<TSource> _()
        {
            foreach (var item in source)
            {
                yield return item;
                if (predicate(item))
                    yield break;
            }
        }
    }
}

您可以将方法简化如下:

Enumerable
    .Range(0, maxPages)
    .Select(i => i * maxLimit)
    .Select(offset => api3.SearchQuery(searchTerm, maxLimit, offset))
    .TakeUntil(a => a.Items.Count < maxLimit)
    .SelectMany(a => a.Items)
    .ToArray();

Csharp相关问答推荐

在实际上是List T的 IESEARCH上多次调用First()是否不好?

.NET最小API映射将T参数列表为[FromQuery]

EF Core Fluent API中定义的多对多关系

更改对象的旋转方向

Monty Hall游戏节目模拟给我50/50的结果

Elasticsearch:当我try 使用c#将嵌套对象添加到filter中时出现问题

Azure DEVOPS找不到定制的Nuget包

C#-从基类更新子类

单行上的ReSharper数据标注

如何在C#中转换泛型包装类内部的派生类

TagHelpers在新区域不起作用

WinUI 3中DoubleCollection崩溃应用程序类型的依赖属性

在集成测试中可以在模拟InMemory数据库中设定数据种子

System.NotSupportdException:流不支持读取

如何在.NET MAUI上在iOS和Mac之间共享代码?(no条件编译和无代码重复)

将列表转换为带有逗号分隔字符串形式的值的字典

嵌套Blazor组件内的验证

如何在JSON:API中定义的&过滤查询参数系列&标准的GET请求中传递多个相关参数?

无法将.Net Framework 4.8.1升级到.Net 7

C#LINQ多行条件