如何根据某个属性将对象分成块?

3
public class InvestorMailing
{
    public string To { get; set; }

    public IEnumerable<string> Attachments { get; set; }

    public int AttachmentCount { get; set; }

    public long AttachmentSize { get; set; }
}

我是一位有用的助手,可以翻译文本。

我有一个 IList<InvestorMailing> mailingList。如果附件大小大于 x,则需要将对象拆分为块。是否有一种简单的linq-y方法来做到这一点?

编辑:

这是我生成邮件的方式:

        var groupedMailings = mailingList.GroupBy(g => g.GroupBy);

        var investorMailings = groupedMailings.Select(
            g => new DistinctInvestorMailing
            {
                Id = g.Select(x => x.Id).FirstOrDefault(),
                To = g.Key.Trim(),
                From = g.Select(x => x.From).FirstOrDefault(),
                FromName = g.Select(x => x.FromName).FirstOrDefault(),
                Bcc = g.Select(x => x.Bcc).FirstOrDefault(),
                DeliveryCode = g.Select(x => x.DeliveryCode).FirstOrDefault(),
                Subject = g.Select(x => x.Subject).FirstOrDefault(),
                Body = g.Select(x => x.Body).FirstOrDefault(),
                CommentsOnStatus = g.Select(x => x.CommentsOnStatus).FirstOrDefault(),
                Attachments = g.Select(x => x.AttachmentPath),
                AttachmentCount = g.Select(x => x.AttachmentPath).Count(),
                AttachmentSize = g.Sum(x => x.AttachmentSize),
                MailType = g.Select(x => x.MessageType).FirstOrDefault()
            }
        ).ToList();

你想要分割什么?是InvestorMailings列表还是单个InvestorMailing的附件? - dtb
InventorMailing是一个对象,每个对象都有自己的AttachmentCount属性。您想要进行拆分的时间是什么时候?即使列表中的单个项目大于x,您是否也要拆分? - azamsharp
几乎与http://stackoverflow.com/questions/2678008/how-to-split-linq-grouping相同。 - Mark Byers
如果附件大小大于x,我想将单个InvestorMailing拆分。例如,maxAttachmentSize为10mb。因此,如果InvestorMailing AttachmentSize为30mb,则我希望有3个InvestorMailings。 - CurlyFro
@CurlyFro:InvestorMailingDistrictInvestorMailing之间有什么区别? - Mark Byers
InvestorMailing邮件列表是一个扁平列表,其中To具有重复项,而AttachmentPath对于每个To是唯一的。DistrictInvestorMailing将Tos分组,其中每个唯一的To具有多个附件(即AttachmentPaths)。 - CurlyFro
3个回答

1

使用标准方法应该很容易做到。考虑以下示例:

class Foo
{
    public Foo(int weight) { Weight = weight; }
    public int Weight { get; set; }
}

...

IEnumerable<IList<Foo>> GroupFoosByWeight(IList<Foo> foos, int weightLimit)
{
    List<Foo> list = new List<Foo>();
    int sumOfWeight = 0;

    foreach (Foo foo in foos)
    {
        if (sumOfWeight + foo.Weight > weightLimit)
        {
            yield return list;
            sumOfWeight = 0;
            list.Clear();
        }

        list.Add(foo);
        sumOfWeight += foo.Weight;
    }

    if (list.Count > 0)
        yield return list;
}

...

List<Foo> foos = new List<Foo>()
{
    new Foo(15), new Foo(32), new Foo(14), new Foo(19), new Foo(27)
};

foreach (IList<Foo> list in GroupFoosByWeight(foos, 35))
{
    Console.WriteLine("{0}\t{1}", list.Count, list.Sum(f => f.Weight));
}

编辑

我稍微修改了一下,写了一个LINQ版本。在这种情况下它并没有节省太多的代码,但这是一个开始。

int weightLimit = 35;
int fooGroup = 0;
int totalWeight = 0;

Func<Foo, int> groupIncrementer = f =>
{
    if (totalWeight + f.Weight > weightLimit)
    {
        fooGroup++;
        totalWeight = 0;
    }

    totalWeight += f.Weight;

    return fooGroup;
};

var query = from foo in foos
            group foo by new { Group = groupIncrementer(foo) }
                into g
                select g.AsEnumerable();

foreach (IList<Foo> list in query)
{
    Console.WriteLine("{0}\t{1}", list.Count, list.Sum(f => f.Weight));
}

1

以下是一种使用LINQ查找具有足够空间添加附件的块的方法:

var chunks = new List<List<InvestorMailing>>();
int maxAttachmentsSize = 10;

foreach (InvestorMailing mail in mailingList)
{
    var chunkWithSpace = chunks
        .Where(list => list.Sum(x => x.AttachmentSize) +
                       mail.AttachmentSize <= maxAttachmentsSize)
        .FirstOrDefault();

    if (chunkWithSpace != null)
    {
        chunkWithSpace.Add(mail);
    } else {
        chunks.Add(new List<InvestorMailing> { mail });
    }
}

结果存储在chunks中。


0

是的:

var highs = mailingList.Where(i => i.AttachmentSize > 10000).ToList();
var lows = mailingList.Where(i => i.AttachmentSize <= 10000).ToList();

除此之外,你需要如何将它们分开?

希望对你有所帮助。


我认为他想要批处理这些事情。因此,一旦超过某个给定的阈值,执行一个动作并继续。所以它不是单个大小,而是集体大小。 - Anthony Pegram

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接