Take 1000 using LINQ

本文关键字:LINQ using 1000 Take | 更新日期: 2023-09-27 18:35:12

好的,我的linq技能不是很好,所以我尝试执行以下操作。

假设我有 6000 条记录(电子邮件地址)我想将前 1000 个添加到密件抄送,发送,将接下来的 1000 个添加到密件抄送,发送,将 1000 添加到密件抄送、发送等。

我开始扭动,

string[] files = System.IO.Directory.GetFiles(@"C:'Mail' ", "*.csv");
Parallel.ForEach(files, currentFile =>
{
    string filename = currentFile;
    StreamReader reader = new StreamReader(filename);
    var emailList = new List<String>();
    while (reader.Peek() >= 0)
    {
        emailList.Add(reader.ReadLine());
    }
    ''Here is where I need to do the linq?
    IEnumerable<string> list = emailList
    var message = new System.Net.Mail.MailMessage();
    foreach (var s in list)
    {
        MailAddress mailAddress = new MailAddress(s);
        message.Bcc.Add(mailAddress);
    }
    message.Subject = txtSubject.Text;
    message.From = new System.Net.Mail.MailAddress(txtFrom.Text);
    message.Body = txtMessage.Text;
    message.IsBodyHtml = true;
    var smtp = new System.Net.Mail.SmtpClient();
    smtp.Send(message);

Take 1000 using LINQ

您似乎正在寻找一种Batch方法。 下面是一个实现:

public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int batchSize)
{
    List<T> buffer = new List<T>(batchSize);
    foreach (T item in source)
    {
        buffer.Add(item);
        if (buffer.Count >= batchSize)
        {
            yield return buffer;
            buffer = new List<T>(batchSize);
        }
    }
    if (buffer.Count > 0)
    {
        yield return buffer;
    }
}

您现在可以编写:

foreach(var batch in emailList.Batch(1000))
{
    var message = CreateMessage();
    foreach(var email in batch)
    {
        message.Bcc.Add(email);
    }
    message.Send();
}

附带说明一下,您可以使用File.ReadLines来获取表示文件中行的IEnumerable<string>,而不是使用StreamReader来读取文件的行。 它甚至还有一个附带的好处,即流式传输数据,而不是先将所有行拉入内存。

将您的电子邮件发送代码移动到一个单独的方法中,并在初始 while 循环中有足够的地址后调用该方法:

var emailList = new List<String>();
while (reader.Peek() >= 0)
{
    emailList.Add(reader.ReadLine());
    if(emailList.Count == 1000)
    {
        SendEmails(emailList);
        emailList = new List<String>();
    }
}
//send the rest, if any
if(emailList.Any()) SendEmails(emailList);

无论如何,这要干净得多,因为您的电子邮件发送方法与您获取电子邮件地址的方式在逻辑上是分开的。

如果你想用linq做到这一点,我相信这个答案会完全符合你的要求,在下面修改,你在组= 1000中发送

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int group)
{
    return  source
        .Select((x, i) => new { Index = i, Value = x })
        .GroupBy(x => x.Index / group)
        .Select(x => x.Select(v => v.Value).ToList())
        .ToList();
}

这应该是一个评论而不是答案。 请让我知道,如果是这种情况,我会删除和更改