提问者:小点点

收益返回保存迭代器的下一个状态


在成批转换列表时,yield return跳过已签入if条件但由于大小限制而未添加到bucket的对象。

消息总计数: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;
        }
    }

共2个答案

匿名用户

您可以将项目添加到收益返回后新创建的列表中:

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

匿名用户

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

首先,当当前bucket不能包含当前消息时,您应该将消息放入下一个bucket,而不是将其丢弃。因此,在foreach循环中返回收益率后,您应该执行以下操作:

bucket = new() { 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;
}     

另外,我不确定最后一个大小的目的是什么

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