Вы хотите элегантно и лаконично, я дам вам элегантный и лаконичный:
var fifties = from index in Enumerable.Range(0, addresses.Length)
group addresses[index] by index/50;
foreach(var fifty in fifties)
Send(string.Join(";", fifty.ToArray());
Зачем возиться со всем этим ужасным циклическим кодом, если в этом нет необходимости? Вы хотите сгруппировать вещи по пятидесяти годам, затем сгруппировать их по пятидесяти годам. Для этого нужен групповой оператор!
ОБНОВЛЕНИЕ: комментатор MoreCoffee спрашивает, как это работает. Предположим, мы хотим сгруппировать по тройкам, потому что так легче набирать.
var threes = from index in Enumerable.Range(0, addresses.Length)
group addresses[index] by index/3;
Предположим, что существует девять адресов, проиндексированных от нуля до восьми
Что означает этот запрос?
Enumerable.Range
- это диапазон из девяти чисел, начинающихся с нуля, поэтому 0, 1, 2, 3, 4, 5, 6, 7, 8
.
] Переменная диапазона index
принимает каждое из этих значений по очереди.
Затем мы перебираем каждый соответствующий адрес [index]
и назначаем его группе.
Какая группа мы его назначаем? Группе index / 3
. Целочисленное арифметическое округление до нуля в C #, поэтому индексы 0, 1 и 2 становятся 0 при делении на 3. Индексы 3, 4, 5 становятся 1 при делении на 3. Индексы 6, 7, 8 становятся 2.
Таким образом, мы назначаем адресов [0]
, адресов [1]
и адресов [2]
группе 0, адресов [3]
, адреса [4]
и адреса [5]
для группы 1 и т. Д.
Результатом запроса является последовательность из трех групп, и каждая группа представляет собой последовательность из трех элементов.
Имеет ли это смысл?
Помните также, что результатом выражения запроса является запрос , который представляет эту операцию . не выполняет операцию до тех пор, пока не будет выполнен цикл foreach
.
адреса [4]
и адреса [5]
для группы 1 и т. Д.
Результатом запроса является последовательность из трех групп, и каждая группа представляет собой последовательность из трех элементов.
Имеет ли это смысл?
Помните также, что результатом выражения запроса является запрос , который представляет эту операцию . не выполняет операцию до тех пор, пока не будет выполнен цикл foreach
.
адреса [4]
и адреса [5]
для группы 1 и т. Д.
Результатом запроса является последовательность из трех групп, и каждая группа представляет собой последовательность из трех элементов.
Имеет ли это смысл?
Помните также, что результатом выражения запроса является запрос , который представляет эту операцию . не выполняет операцию до тех пор, пока не будет выполнен цикл foreach
.
Похоже, что вход состоит из отдельных строк адресов электронной почты в большом массиве, а не нескольких адресов электронной почты в одной строке, верно? И в выходных данных каждая партия представляет собой одну объединенную строку.
string[] allAddresses = GetLongArrayOfAddresses();
const int batchSize = 50;
for (int n = 0; n < allAddresses.Length; n += batchSize)
{
string batch = string.Join(";", allAddresses, n,
Math.Min(batchSize, allAddresses.Length - n));
// use batch somehow
}
Я бы просто перебрал массив и использовал StringBuilder для создания списка (я предполагаю, что он разделен; как вы сделали бы для электронной почты). Просто отправьте, когда вы нажмете мод 50 или конец.
void Foo(string[] addresses)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < addresses.Length; i++)
{
sb.Append(addresses[i]);
if ((i + 1) % 50 == 0 || i == addresses.Length - 1)
{
Send(sb.ToString());
sb = new StringBuilder();
}
else
{
sb.Append("; ");
}
}
}
void Send(string addresses)
{
}
Я думаю, что это просто и достаточно быстро. Пример ниже делит длинное предложение на 15 частей, но вы можете передать размер пакета в качестве параметра, чтобы сделать его динамичным. Здесь я просто делю, используя "/n".
private static string Concatenated(string longsentence)
{
const int batchSize = 15;
string concatanated = "";
int chanks = longsentence.Length / batchSize;
int currentIndex = 0;
while (chanks > 0)
{
var sub = longsentence.Substring(currentIndex, batchSize);
concatanated += sub + "/n";
chanks -= 1;
currentIndex += batchSize;
}
if (currentIndex < longsentence.Length)
{
int start = currentIndex;
var finalsub = longsentence.Substring(start);
concatanated += finalsub;
}
return concatanated;
}
Показывает результат операции разделения.
var parts = Concatenated(longsentence).Split(new string[] { "/n" }, StringSplitOptions.None);
Методы расширения, основанные на ответе Эрика :
public static IEnumerable<IEnumerable<T>> SplitIntoChunks<T>(this T[] source, int chunkSize)
{
var chunks = from index in Enumerable.Range(0, source.Length)
group source[index] by index / chunkSize;
return chunks;
}
public static T[][] SplitIntoArrayChunks<T>(this T[] source, int chunkSize)
{
var chunks = from index in Enumerable.Range(0, source.Length)
group source[index] by index / chunkSize;
return chunks.Select(e => e.ToArray()).ToArray();
}
Похоже на этот вопрос: Разделить коллекцию на n частей с помощью LINQ?
Измененная версия ответа Хасана Хана должна сделать трюк:
public static IEnumerable<IEnumerable<T>> Chunk<T>(
this IEnumerable<T> list, int chunkSize)
{
int i = 0;
var chunks = from name in list
group name by i++ / chunkSize into part
select part.AsEnumerable();
return chunks;
}
Пример использования:
var addresses = new[] { "a@example.com", "b@example.org", ...... };
foreach (var chunk in Chunk(addresses, 50))
{
SendEmail(chunk.ToArray(), "Buy V14gr4");
}
Предполагая, что вы используете .NET 3.5 и C # 3, что-то вроде этого должно работать нормально:
string[] s = new string[] {"1", "2", "3", "4"....};
for (int i = 0; i < s.Count(); i = i + 50)
{
string s = string.Join(";", s.Skip(i).Take(50).ToArray());
DoSomething(s);
}
Я думаю, что нам нужно немного больше узнать, как именно выглядит этот список, чтобы дать окончательный ответ. На данный момент я предполагаю, что это список адресов электронной почты, разделенных точкой с запятой. В таком случае вы можете сделать следующее, чтобы получить список по частям.
public IEnumerable<string> DivideEmailList(string list) {
var last = 0;
var cur = list.IndexOf(';');
while ( cur >= 0 ) {
yield return list.SubString(last, cur-last);
last = cur + 1;
cur = list.IndexOf(';', last);
}
}
public IEnumerable<List<string>> ChunkEmails(string list) {
using ( var e = DivideEmailList(list).GetEnumerator() ) {
var list = new List<string>();
while ( e.MoveNext() ) {
list.Add(e.Current);
if ( list.Count == 50 ) {
yield return list;
list = new List<string>();
}
}
if ( list.Count != 0 ) {
yield return list;
}
}
}