3

i am sending out email to a list of people. I have the list of recipients in array but the list can get up to 500 people. There is a limitation on the number of recipients that my mail server sends out at once (50 recipients)

so if the list is > 50 i need to break it up in to different mails.

What is the best way to take one array and break it up into arrays of 50

for example:

if array is 120 long, i would expect 3 arrays returned, one with 50, another with 50 and a third with 20.

skaffman
  • 398,947
  • 96
  • 818
  • 769
leora
  • 188,729
  • 360
  • 878
  • 1,366
  • possible duplicate of [Split List into Sublists with LINQ](http://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq) – nawfal Feb 18 '13 at 12:10

6 Answers6

8

You could use the Batch operation from MoreLINQ:

Person[] array = ...;

var arrays = list.Batch(50).Select(x = x.ToArray());

foreach (Person[] shorterArray in arrays)
{
    ...
}

(If you're happy with IEnumerable<Person> instead of arrays, you don't need the Select call of course.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • i just have an array of string and can't seem to find teh Batch method in morelinq – leora Sep 02 '09 at 14:17
  • The first link shows you the Batch method. It's an extension method on `IEnumerable`. You just need a `using MoreLINQ;` directive in your code. – Jon Skeet Sep 02 '09 at 14:30
5

Maybe ArraySegment<T> works for you? You'd have to split it up manually though, but this is not hard in a loop.

int recipient = 0;
while (recipient < recipients.Count) {
  ArraySegment<string> recipientSegment = new ArraySegment<string>(recipients, recipient, Math.Min(50, recipients.Count-recipient));
  // build your message here, using the recipientSegment for the names
  recipient += 50;
}
Lucero
  • 59,176
  • 9
  • 122
  • 152
3

I would simply iterate over the complete array, building up the recipients string, then sending out an email when the limit is reached, then resetting the string and continuing on with the iteration until the next limit event or until the end of the array is reached.

1

If you can use LINQ when you may find this useful: Linq: How to group by maximum number of items

Community
  • 1
  • 1
okutane
  • 13,754
  • 10
  • 59
  • 67
0

A common method for "paging" results from a set is to combine the Skip and Take methods provided by LINQ. This solution is great because it can be further combined with other LINQ methods to implement filtering, ordering, etc. as needed.

I'm not sure what the performance considerations are for your application, so keep in mind that this may not perform very well for sets where the number of pages is relatively large (i.e., batch size is significantly smaller than the total size of the set), but it's at least fairly straightforward for anyone familiar with this style of coding.

Here's an example of what this implementation might look like:

List<EmailAddress> list = new List<EmailAddress>();
const int BATCH_SIZE = 50;

for (int i = 0; i < list.Count; i += BATCH_SIZE)
{
   IEnumerable<EmailAddress> currentBatch = 
      list.Skip(i).Take(BATCH_SIZE);

   // do stuff...
}
jeremyalan
  • 4,658
  • 2
  • 29
  • 38
0

Shouldn't LINQ be the right stuff for this?

Quamis
  • 10,924
  • 12
  • 50
  • 66