Вопрос по string, arrays, c# – C #: Самый простой способ разделить массив строк на N экземпляров длиной N элементов

21

Я знаю, как сделать это безобразно, но мне интересно, есть ли более элегантный и лаконичный метод.

У меня есть строковый массив адресов электронной почты. Предположим, что массив строк имеет произвольную длину - он может содержать несколько элементов или может содержать очень много элементов. Я хочу построить еще одну строку, состоящую из, скажем, 50 адресов электронной почты из массива строк до конца массива, и вызывать операцию отправки после каждых 50, используя строку из 50 адресов в методе Send ().

В более общем плане вопрос заключается в том, какой самый чистый / ясный способ сделать подобные вещи. У меня есть решение, которое является наследием моих знаний VBScript, но я держу пари, что в C # есть лучший способ.

возможный дубликатSplit List into Sublists with LINQ nawfal
Спасибо всем за удивительные ответы - действительно, ваши методы были намного лучше, чем простое циклическое решение, которое я реализовывал в былые времена. Это было именно то руководство, которое я надеялся получить! Socrates

Ваш Ответ

8   ответов
0

что это просто и достаточно быстро. Пример ниже делит длинное предложение на 15 частей, но вы можете передать размер пакета в качестве параметра, чтобы сделать его динамичным. Здесь я просто делю, используя & quot; / n & quot ;.

 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);
0

Ответ Эрика:

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();
}
0

нам нужно немного больше узнать о том, как именно выглядит этот список, чтобы дать окончательный ответ. На данный момент я предполагаю, что это список адресов электронной почты, разделенных точкой с запятой. Если это так, вы можете сделать следующее, чтобы получить разделенный список.

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;
     }
  }
}
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
2

что вы используете .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);
}
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
49

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());

Зачем возиться со всем этим ужасным цикличным кодом, когда вам это не нужно? Вы хотите сгруппировать вещи к пятидесятым,then group them by fifties. That's what the group operator is for!

ОБНОВЛЕНИЕ: комментатор 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 принимает каждое из этих значений по очереди.

Затем мы переходим каждый соответствующийaddresses[index] и назначить его группе.

На какую группу мы его назначаем? В группуindex/3, Целочисленные арифметические циклы округляются к нулю в C #, поэтому индексы 0, 1 и 2 становятся 0 при делении на 3. Индексы 3, 4, 5 становятся 1, когда делятся на 3. Индексы 6, 7, 8 становятся 2.

Итак, мы назначаемaddresses[0], addresses[1] а такжеaddresses[2] к группе 0,addresses[3], addresses[4] а такжеaddresses[5] в группу 1 и так далее.

Результатом запроса является последовательность из трех групп, и каждая группа представляет собой последовательность из трех элементов.

Имеет ли это смысл?

Помните также, что результатquery expression этоquery which represents this operation, Это неperform операция доforeach цикл выполняется.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Красиво :-) +1
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
2

что вход состоит из отдельных строк адреса электронной почты в большом массиве, а не нескольких адресов электронной почты в одной строке, верно? И в выходных данных каждая партия представляет собой одну объединенную строку.

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
}
1

писка (я предполагаю, что он разделен; как вы сделали бы для электронной почты). Просто отправьте, когда вы нажмете мод 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)
{
}
14

Разделить коллекцию на n частей с помощью LINQ?

Модифицированная версияHasan Khanответ должен сделать свое дело:

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[] { "[email protected]", "[email protected]", ...... };

foreach (var chunk in Chunk(addresses, 50))
{
    SendEmail(chunk.ToArray(), "Buy V14gr4");
}
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы