【问题标题】:Yield return saves the next state of iteratoryield return 保存迭代器的下一个状态
【发布时间】:2022-01-15 05:51:56
【问题描述】:

在批量转换列表时,yield return 会跳过已在 if 条件下签入但由于大小限制未添加到存储桶中的对象。

消息总数:4
第一个桶数:2
第二桶数:1
消息列表中的第三条消息被跳过。
在这里,我正在创建大小为 250kb 的存储桶。还有其他方法可以保存正确的状态还是我需要使用 for 循环?

  public static IEnumerable<IEnumerable<Message>> GetBatchSize(IList<Message> source)
    {
        List<Message> bucket = null;
        long size = 0;
        foreach (var item in source)
        {

                if (bucket == null)
                {
                    bucket = new List<Message>();
                }
                size = size + item.Size;
            if (250 - (size / 1024) >= item.Size / 1024)
            {
                bucket.Add(item);
                continue;
            }             
            yield return bucket;
            bucket = new List<Message>();
            size = 0;
        }

        if (bucket?.Count > 0 && size<250)
        {
            yield return bucket;
        }
    }

【问题讨论】:

    标签: c# .net recursion c#-4.0 yield-return


    【解决方案1】:

    (假设没有单个消息的大小大于桶大小)

    首先,当当前桶不能包含当前消息时,应将消息放入下一个桶,而不是扔掉。所以在foreach循环中返回yield之后,你应该这样做:

    bucket = new() { item };
                   ^^^^^^^^
    

    此外,您将项目添加到存储桶的条件也不正确。它“双重计算”当前项目的大小。请注意,此时size 已经添加了item.Size!另外,这里使用除法会丢弃余数,这会导致在以下情况下产生不正确的结果:

    GetBatchSize(new List<Message> {
        new Message { Size = 250 * 1024 - 1 },
        new Message { Size = 1 },
        new Message { Size = 1 },
    });
    

    不是除法,而是乘法:

    if (size <= 250 * 1024)
    {
        bucket.Add(item);
        continue;
    }     
    

    另外,我不确定最后一次size &lt; 250 检查的目的是什么。你的意思可能是size &lt; 250 * 1024,但由于循环的不变性,这应该总是正确的,所以你可以删除它:

    if (bucket?.Count > 0)
    {
        yield return bucket;
    }
    

    【讨论】:

      【解决方案2】:

      你可以在yield返回后将item添加到你新创建的列表中:

      foreach (var item in source)
      {
         // omitted for brevity
         yield return bucket;
         bucket = new List<Message> { item };
         size = item.Size;
      }
      

      【讨论】:

        猜你喜欢
        • 2019-07-05
        • 1970-01-01
        • 1970-01-01
        • 2011-01-25
        • 2012-10-19
        • 2010-11-08
        • 2014-05-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多