Разделить строку в 512 char кусках

Возможно, основной вопрос, но скажем, что у меня есть строка длиной 2000 символов, мне нужно разбить эту строку на максимальные 512 символов.

Есть ли хороший способ, например, цикл или так для этого?

Ответ 1

Что-то вроде этого:

private IList<string> SplitIntoChunks(string text, int chunkSize)
{
    List<string> chunks = new List<string>();
    int offset = 0;
    while (offset < text.Length)
    {
        int size = Math.Min(chunkSize, text.Length - offset);
        chunks.Add(text.Substring(offset, size));
        offset += size;
    }
    return chunks;
}

Или просто перебрать:

private IEnumerable<string> SplitIntoChunks(string text, int chunkSize)
{
    int offset = 0;
    while (offset < text.Length)
    {
        int size = Math.Min(chunkSize, text.Length - offset);
        yield return text.Substring(offset, size);
        offset += size;
    }
}

Обратите внимание, что это разделяется на куски кодовых единиц UTF-16, что не совсем то же самое, что разделение на куски кодовых точек Unicode, что, в свою очередь, может быть не таким, как разбиение на куски глифов.

Ответ 2

используя реализацию Jon и ключевое слово yield.

IEnumerable<string> Chunks(string text, int chunkSize)
{
    for (int offset = 0; offset < text.Length; offset += chunkSize)
    {
        int size = Math.Min(chunkSize, text.Length - offset);
        yield return text.Substring(offset, size);
    }
}

Ответ 3

Хотя этот вопрос между тем имеет принятый ответ, здесь короткая версия с помощью регулярных выражений. Пуристам может не нравиться это (понятно), но когда вам нужно быстрое решение, и вам удобно с регулярными выражениями, это может быть и так. Производительность довольно хороша, удивительно:

string [] split = Regex.Split(yourString, @"(?<=\G.{512})");

Что он делает? Отрицательный внешний вид и запоминание последней позиции с помощью \G. Он также поймает последний бит, даже если он не делится на 512.

Ответ 5

Я осмелюсь предоставить более LINQified версию решения Jon, основанную на том, что тип string реализует IEnumerable<char>:

private IList<string> SplitIntoChunks(string text, int chunkSize)
{
    var chunks = new List<string>();
    int offset = 0;
    while(offset < text.Length) {
        chunks.Add(new string(text.Skip(offset).Take(chunkSize).ToArray()));
        offset += chunkSize;
    }
    return chunks;
}

Ответ 6

Большая часть ответа может иметь тот же недостаток. Учитывая пустой текст, они ничего не принесут. Мы (I) ожидаем, что, по крайней мере, вернем эту пустую строку (такое же поведение, как разделение на char не в строке, что даст один элемент: данная строка)

поэтому мы должны зацикливаться хотя бы один раз все время (на основе кода Джона):

IEnumerable<string> SplitIntoChunks (string text, int chunkSize)
{
    int offset = 0;
    do
    {
        int size = Math.Min (chunkSize, text.Length - offset);
        yield return text.Substring (offset, size);
        offset += size;
    } while (offset < text.Length);
}

или с помощью параметра for (Edited): после того, как он немного поработал с этим, я нашел лучший способ обработать случай chunkSize больше, чем текст):

IEnumerable<string> SplitIntoChunks (string text, int chunkSize)
{
    if (text.Length <= chunkSize)
        yield return text;
    else
    {
        var chunkCount = text.Length / chunkSize;
        var remainingSize = text.Length % chunkSize;

        for (var offset = 0; offset < chunkCount; ++offset)
            yield return text.Substring (offset * chunkSize, chunkSize);

        // yield remaining text if any
        if (remainingSize != 0)
            yield return text.Substring (chunkCount * chunkSize, remainingSize);
    }
}

Это также можно использовать с циклом do/while;)

Ответ 7

Общий метод расширения:

using System;
using System.Collections.Generic;
using System.Linq;

public static class IEnumerableExtensions
{
  public static IEnumerable<IEnumerable<T>> SplitToChunks<T> (this IEnumerable<T> coll, int chunkSize)
  {
    int skipCount = 0;
    while (coll.Skip (skipCount).Take (chunkSize) is IEnumerable<T> part && part.Any ())
    {
      skipCount += chunkSize;
      yield return part;
    }
  }
}

class Program
{
  static void Main (string[] args)
  {
    var col = Enumerable.Range(1,1<<10);
    var chunks = col.SplitToChunks(8);

    foreach (var c in chunks.Take (200))
    {
      Console.WriteLine (string.Join (" ", c.Select (n => n.ToString ("X4"))));
    }

    Console.WriteLine ();
    Console.WriteLine ();

    "Split this text into parts that are fifteen characters in length, surrounding each part with single quotes and output each into the console on seperate lines."
      .SplitToChunks (15)
      .Select(p => $"'{string.Concat(p)}'")
      .ToList ()
      .ForEach (p => Console.WriteLine (p));

    Console.ReadLine ();
  }
}

Ответ 8

Что-то вроде?

Calculate eachLength = StringLength / WantedCharLength
Then for (int i = 0; i < StringLength; i += eachLength)
SubString (i, eachLength);