C#需要递归帮助

时间:2011-03-29 20:50:59

标签: c# recursion

在我们的Windows应用程序中,我们有startDate和EndDate。点击执行按钮事件,我们需要使用我们的搜索字符串+日期范围(日期从01/01/2010到12/31/2010)调用第三方Web服务。现在我们的搜索条件可以返回数千条记录,但是Web服务的限制是每个事务只能返回10K条记录。

这要求我们分解dateRange。所以基本上我们需要关注;

For(X dateRange if RecordCount> 10000)then X dateRange / 2将于01/01/2010至06/01/2010在我们的情况下再次检查条件并递归执行此操作直到我们得到RecordCount为< 10000

然后从下一个日期开始,例如,如果我们从01/01/2010到03/30/2010获得9999条记录,那么我们需要从04/01/2010开始获取下一个区块的记录

Recursion可以实现吗?

RecursionFunction(dtStart, dtEnd)
{
  if (WebService.RecordCount > 9999)
     {
                TimeSpan timeSpan = dtEnd.Subtract(dtStart);
                DateTime mStart = dtStart;
                DateTime mEnd = dtStart.AddDays(timeSpan.Days / 2);
                RecursionFunction(dtStart,dtEnd);
      }
  else
   {
     Get Records here
    }
}

但是使用上面的代码,递归会有以下块

01/01/2010,12/31/2010> 10000 01/01 / 2010,07 / 03/2010> 10000 01/01 / 2010,04 / 02/2010< 10000

因此,在完成记录之后,递归将从块01/01 / 2010,07 / 03/2010再次开始,我们不需要。我们需要在04/03 / 2010,12 / 31/2010

开始下一次递归

提前感谢您的帮助。

6 个答案:

答案 0 :(得分:1)

第一步是将RecursionFunction调用(在您的示例的第8行)更改为:

RecursionFunction(mStart, mEnd);

但是,那么,您还需要再次使用日期范围的另一半来调用它。

RecursionFunction(mEnd + AddDays(1), dtEnd);

此外,您需要处理结果(可能结合两个答案)。

var set1 = RecurseFunction(...);
var set2 = RecurseFunction(...);
return set1.Concat(set2);

答案 1 :(得分:1)

看起来你正试图将输入范围分开,直到它足够小才能处理。尝试为两个范围调用它:

RecursionFunction(mStart, mEnd);
RecursionFunction(mEnd.AddDays(1), dtEnd);

答案 2 :(得分:1)

这就像分而治之。您需要从拆分的左侧和右侧获取结果并将它们组合并返回该值。所以你可以继续变小,直到你有足够的数据可以处理,然后返回。然后继续将结果集连接在一起。

public IList<Data> GetRecords(DateTime start, DateTime end)
{
    var RecordCount = WebService.RecordCount(start, end);
    if (RecordCount < 10000) return WebService.GetRecords(start, end);
    DateTime l, m, e;
    l = start;
    e = end;
    var midDay = end.Subtract(start).TotalDays / 2;
    m = start.AddDays(midDay);

    var left = GetRecords(l, m);
    var right = GetRecords(m.AddDays(1), e);

    return left.Concat(right);
}

答案 3 :(得分:0)

一种简单的方式是一种分页形式。如果您使用JSON或XML,则可以输入总结果量并返回一组设置的结果(也返回偏移量)。通过这种方式,您可以循环检查您是否在最后一页上以及在获得最后一个结果页面后,确定是否已经完成。

如果特定交易失败,请不要忘记检查。它不是这么大的数据集的理想解决方案,但它是一种解决方法

答案 4 :(得分:0)

对于你在while循环中实际返回的数据而言,重复使用最后一个日期比使用这样的递归回家要容易得多。

  

然后从下一个日期开始,例如,如果我们从01/01/2010到03/30/2010获得9999条记录,那么我们需要从04/01/2010开始获取下一个区块的记录

3月有31天。

伪C#代码

var dtStart = DateTime.Parse("2010-01-01");
var dtEnd = DateTime.Parse("2010-12-31");

var totalRecords = new List<RecordType>();
var records = WebService.Get(dtStart, dtEnd);
totalRecords.Add(records);
while (dtStart < dtEnd && records.Count > 9999)
{
    dtStart=records.Last().Date;
    records = WebService.Get(dtStart, dtEnd);
    totalRecords.Add(records);
}

为了减轻服务负担,您可以计算上一次运行的时间跨度,并且只能在while循环中为下一次运行获取那么多天。

如何处理不可避免的双峰取决于记录中的数据。

我刚才意识到我假设你在返回的数据中有一个日期。如果没有,那么忽略这个答案。

答案 5 :(得分:0)

我就是这样做的

static List<string> RecursiveGet(DateTime StartDate, DateTime EndDate, List<string> Output)
{
    if (Webservice.RecordCount > 9999)
    {
        TimeSpan T = EndDate.Subtract(StartDate);
        T = new TimeSpan((long)(T.Ticks / 2));
        DateTime MidDate = StartDate.Add(T);
        Output.AddRange(RecursiveGet(StartDate, MidDate, Output));
        Output.AddRange(RecursiveGet(MidDate.AddMilliseconds(1), EndDate, Output));
    }
    else
    {
        //Get Records here, return them in array
        Output.Add("Test");
    }
    return Output;
}
static List<string> GetRecords(DateTime StartDate, DateTime EndDate)
{
    return RecursiveGet (StartDate, EndDate, new List<string>());
}

注意,无法测试
它的工作原理是将日期分成两半,然后搜索每一个,如果一个仍然大于9999,那么再做一次。

相关问题