Разделение строки на куски определенного размера

Предположим, что у меня была строка:

string str = "1111222233334444"; 

Как я могу разбить эту строку на куски какого-то размера?

например, разбить это на 4 размера, вернет строки:

"1111"
"2222"
"3333"
"4444"

Ответ 1

static IEnumerable<string> Split(string str, int chunkSize)
{
    return Enumerable.Range(0, str.Length / chunkSize)
        .Select(i => str.Substring(i * chunkSize, chunkSize));
}

Обратите внимание, что для изящного управления крайними случаями может потребоваться дополнительный код (null или пустая строка ввода, chunkSize == 0, длина входной строки не делится на chunkSize и т.д.). В исходном вопросе не указаны какие-либо требования к этим краевым случаям, и в реальной жизни требования могут варьироваться, поэтому они не входят в сферу действия этого ответа.

Ответ 2

В сочетании с голубем + Константин отвечает...

static IEnumerable<string> WholeChunks(string str, int chunkSize) {
    for (int i = 0; i < str.Length; i += chunkSize) 
        yield return str.Substring(i, chunkSize);
}

Это будет работать для всех строк, которые могут быть разбиты на целые числа кусков, и в противном случае генерирует исключение.

Если вы хотите поддерживать строки любой длины, вы можете использовать следующий код:

static IEnumerable<string> ChunksUpto(string str, int maxChunkSize) {
    for (int i = 0; i < str.Length; i += maxChunkSize) 
        yield return str.Substring(i, Math.Min(maxChunkSize, str.Length-i));
}

Однако OP явно заявляет, что он не нуждается в этом; его несколько длиннее и труднее читать, немного медленнее. В духе KISS и YAGNI я бы включил первый вариант: возможно, это наиболее эффективная реализация, и она очень короткая, читаемая и, что важно, создает исключение для несоответствующего ввода.

Ответ 3

Почему не петли? Здесь что-то, что сделало бы это достаточно хорошо:

        string str = "111122223333444455";
        int chunkSize = 4;
        int stringLength = str.Length;
        for (int i = 0; i < stringLength ; i += chunkSize)
        {
            if (i + chunkSize > stringLength) chunkSize = stringLength  - i;
            Console.WriteLine(str.Substring(i, chunkSize));

        }
        Console.ReadLine();

Я не знаю, как вы справляетесь с случаем, когда строка не является фактором 4, но не говорит, что вы идете, это невозможно, просто интересно, мотивация для него, если простой цикл для него очень хорошо? Очевидно, что вышеупомянутое может быть очищено и даже включено в качестве метода расширения.

Или, как упоминалось в комментариях, вы знаете это /4, затем

str = "1111222233334444";
for (int i = 0; i < stringLength; i += chunkSize) 
  {Console.WriteLine(str.Substring(i, chunkSize));} 

Ответ 4

Использование регулярных выражений и Linq:

List<string> groups = (from Match m in Regex.Matches(str, @"\d{4}")
                       select m.Value).ToList();

Я считаю, что это более читаемо, но это всего лишь личное мнение. Он также может быть однострочным:).

Ответ 5

Это основано на @dove решении, но реализовано как метод расширения.

Преимущества:

  • Метод расширения
  • Обложка угловых случаев
  • Разделяет строку с любыми символами: цифры, буквы и другие символы

код

public static class EnumerableEx
{    
    public static IEnumerable<string> SplitBy(this string str, int chunkLength)
    {
        if (String.IsNullOrEmpty(str)) throw new ArgumentException();
        if (chunkLength < 1) throw new ArgumentException();

        for (int i = 0; i < str.Length; i += chunkLength)
        {
            if (chunkLength + i > str.Length)
                chunkLength = str.Length - i;

            yield return str.Substring(i, chunkLength);
        }
    }
}

Использование

var result = "bobjoecat".SplitBy(3); // bob, joe, cat

Уточненные тесты удалены для краткости (см. предыдущая версия)

Ответ 6

Как это для однострочника?

List<string> result = new List<string>(Regex.Split(target, @"(?<=\G.{4})", RegexOptions.Singleline));

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

Я уверен, что это не самое эффективное решение, но мне просто нужно было его выбросить.

Ответ 7

Это некрасиво и не быстро, но это работает, это однострочный и он LINQy:

List<string> a = text.Select((c, i) => new { Char = c, Index = i }).GroupBy(o => o.Index / 4).Select(g => new String(g.Select(o => o.Char).ToArray())).ToList();

Ответ 8

Недавно мне пришлось написать что-то, что выполнило это на работе, поэтому я решил опубликовать решение этой проблемы. В качестве дополнительного бонуса функциональность этого решения позволяет разделить строку в противоположном направлении и правильно обрабатывать символы юникода, как ранее упоминалось Марвином Пинто выше. Итак, вот он:

using System;
using Extensions;

namespace TestCSharp
{
    class Program
    {
        static void Main(string[] args)
        {    
            string asciiStr = "This is a string.";
            string unicodeStr = "これは文字列です。";

            string[] array1 = asciiStr.Split(4);
            string[] array2 = asciiStr.Split(-4);

            string[] array3 = asciiStr.Split(7);
            string[] array4 = asciiStr.Split(-7);

            string[] array5 = unicodeStr.Split(5);
            string[] array6 = unicodeStr.Split(-5);
        }
    }
}

namespace Extensions
{
    public static class StringExtensions
    {
        /// <summary>Returns a string array that contains the substrings in this string that are seperated a given fixed length.</summary>
        /// <param name="s">This string object.</param>
        /// <param name="length">Size of each substring.
        ///     <para>CASE: length &gt; 0 , RESULT: String is split from left to right.</para>
        ///     <para>CASE: length == 0 , RESULT: String is returned as the only entry in the array.</para>
        ///     <para>CASE: length &lt; 0 , RESULT: String is split from right to left.</para>
        /// </param>
        /// <returns>String array that has been split into substrings of equal length.</returns>
        /// <example>
        ///     <code>
        ///         string s = "1234567890";
        ///         string[] a = s.Split(4); // a == { "1234", "5678", "90" }
        ///     </code>
        /// </example>            
        public static string[] Split(this string s, int length)
        {
            System.Globalization.StringInfo str = new System.Globalization.StringInfo(s);

            int lengthAbs = Math.Abs(length);

            if (str == null || str.LengthInTextElements == 0 || lengthAbs == 0 || str.LengthInTextElements <= lengthAbs)
                return new string[] { str.ToString() };

            string[] array = new string[(str.LengthInTextElements % lengthAbs == 0 ? str.LengthInTextElements / lengthAbs: (str.LengthInTextElements / lengthAbs) + 1)];

            if (length > 0)
                for (int iStr = 0, iArray = 0; iStr < str.LengthInTextElements && iArray < array.Length; iStr += lengthAbs, iArray++)
                    array[iArray] = str.SubstringByTextElements(iStr, (str.LengthInTextElements - iStr < lengthAbs ? str.LengthInTextElements - iStr : lengthAbs));
            else // if (length < 0)
                for (int iStr = str.LengthInTextElements - 1, iArray = array.Length - 1; iStr >= 0 && iArray >= 0; iStr -= lengthAbs, iArray--)
                    array[iArray] = str.SubstringByTextElements((iStr - lengthAbs < 0 ? 0 : iStr - lengthAbs + 1), (iStr - lengthAbs < 0 ? iStr + 1 : lengthAbs));

            return array;
        }
    }
}

Также приведена ссылка на результаты запуска этого кода: http://i.imgur.com/16Iih.png

Ответ 9

Это должно быть намного быстрее и эффективнее, чем использование LINQ или других подходов, используемых здесь.

public static IEnumerable<string> Splice(this string s, int spliceLength)
{
    if (s == null)
        throw new ArgumentNullException("s");
    if (spliceLength < 1)
        throw new ArgumentOutOfRangeException("spliceLength");

    if (s.Length == 0)
        yield break;
    var start = 0;
    for (var end = spliceLength; end < s.Length; end += spliceLength)
    {
        yield return s.Substring(start, spliceLength);
        start = end;
    }
    yield return s.Substring(start);
}

Ответ 10

public static IEnumerable<IEnumerable<T>> SplitEvery<T>(this IEnumerable<T> values, int n)
{
    var ls = values.Take(n);
    var rs = values.Skip(n);
    return ls.Any() ?
        Cons(ls, SplitEvery(rs, n)) : 
        Enumerable.Empty<IEnumerable<T>>();
}

public static IEnumerable<T> Cons<T>(T x, IEnumerable<T> xs)
{
    yield return x;
    foreach (var xi in xs)
        yield return xi;
}

Ответ 11

Вы можете использовать morelinq от Jon Skeet. Используйте Batch, например:

string str = "1111222233334444";
int chunkSize = 4;
var chunks = str.Batch(chunkSize).Select(r => new String(r.ToArray()));

Это вернет 4 куска для строки "1111222233334444". Если длина строки меньше или равна размеру куска Batch, она возвращает строку как единственный элемент IEnumerable<string>

Для вывода:

foreach (var chunk in chunks)
{
    Console.WriteLine(chunk);
}

и он даст:

1111
2222
3333
4444

Ответ 12

static IEnumerable<string> Split(string str, double chunkSize)
{
    return Enumerable.Range(0, (int) Math.Ceiling(str.Length/chunkSize))
       .Select(i => new string(str
           .Skip(i * (int)chunkSize)
           .Take((int)chunkSize)
           .ToArray()));
}

и другой подход:

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

public class Program
{
    public static void Main()
    {

        var x = "Hello World";
        foreach(var i in x.ChunkString(2)) Console.WriteLine(i);
    }
}

public static class Ext{
    public static IEnumerable<string> ChunkString(this string val, int chunkSize){
        return val.Select((x,i) => new {Index = i, Value = x})
                  .GroupBy(x => x.Index/chunkSize, x => x.Value)
                  .Select(x => string.Join("",x));
    }
}

Ответ 13

Шесть лет спустя o_O

Просто потому, что

    public static IEnumerable<string> Split(this string str, int chunkSize, bool remainingInFront)
    {
        var count = (int) Math.Ceiling(str.Length/(double) chunkSize);
        Func<int, int> start = index => remainingInFront ? str.Length - (count - index)*chunkSize : index*chunkSize;
        Func<int, int> end = index => Math.Min(str.Length - Math.Max(start(index), 0), Math.Min(start(index) + chunkSize - Math.Max(start(index), 0), chunkSize));
        return Enumerable.Range(0, count).Select(i => str.Substring(Math.Max(start(i), 0),end(i)));
    }

или

    private static Func<bool, int, int, int, int, int> start = (remainingInFront, length, count, index, size) =>
        remainingInFront ? length - (count - index) * size : index * size;

    private static Func<bool, int, int, int, int, int, int> end = (remainingInFront, length, count, index, size, start) =>
        Math.Min(length - Math.Max(start, 0), Math.Min(start + size - Math.Max(start, 0), size));

    public static IEnumerable<string> Split(this string str, int chunkSize, bool remainingInFront)
    {
        var count = (int)Math.Ceiling(str.Length / (double)chunkSize);
        return Enumerable.Range(0, count).Select(i => str.Substring(
            Math.Max(start(remainingInFront, str.Length, count, i, chunkSize), 0),
            end(remainingInFront, str.Length, count, i, chunkSize, start(remainingInFront, str.Length, count, i, chunkSize))
        ));
    }

AFAIK обрабатываются все ребра.

Console.WriteLine(string.Join(" ", "abc".Split(2, false))); // ab c
Console.WriteLine(string.Join(" ", "abc".Split(2, true))); // a bc
Console.WriteLine(string.Join(" ", "a".Split(2, true))); // a
Console.WriteLine(string.Join(" ", "a".Split(2, false))); // a

Ответ 14

Простой и короткий:

// this means match a space or not a space (anything) up to 4 characters
var lines = Regex.Matches(str, @"[\s\S]{0,4}").Cast<Match>().Select(x => x.Value);

Ответ 15

static IEnumerable<string> Split(string str, int chunkSize)
{
   IEnumerable<string> retVal = Enumerable.Range(0, str.Length / chunkSize)
        .Select(i => str.Substring(i * chunkSize, chunkSize))

   if (str.Length % chunkSize > 0)
        retVal = retVal.Append(str.Substring(str.Length / chunkSize * chunkSize, str.Length % chunkSize));

   return retVal;
}

Он правильно обрабатывает длину входной строки, не делимую на chunkSize.

Обратите внимание, что для изящной обработки краевых случаев может потребоваться дополнительный код (пустая или пустая строка ввода, chunkSize == 0).

Ответ 16

Важным советом, если строка, которая находится в режиме chunked, должна поддерживать все символы Unicode.

Если строка поддерживает международные символы, такие как 𠀋, разделите строку, используя класс System.Globalization.StringInfo. Используя StringInfo, вы можете разбить строку на основе количества текстовых элементов.

string internationalString = '𠀋';

Вышеприведенная строка имеет длину 2, так как свойство String.Length возвращает число Char объектов в этом экземпляре, а не число символов Unicode.

Ответ 17

Лучший, простой и общий ответ:).

    string originalString = "1111222233334444";
    List<string> test = new List<string>();
    int chunkSize = 4; // change 4 with the size of strings you want.
    for (int i = 0; i < originalString.Length; i = i + chunkSize)
    {
        if (originalString.Length - i >= chunkSize)
            test.Add(originalString.Substring(i, chunkSize));
        else
            test.Add(originalString.Substring(i,((originalString.Length - i))));
    }

Ответ 18

Лично я предпочитаю свое решение: -)

Он обрабатывает:

  • Строковые длины, кратные размеру блока.
  • Строковые длины, которые НЕ являются кратными размеру блока.
  • Строковые длины, размер которых меньше размера блока.
  • NULL и пустые строки (генерирует исключение).
  • Размер блоков меньше 1 (генерирует исключение).

Он реализуется как метод расширения, и он вычисляет количество блоков, которые будут генерироваться заранее. Он проверяет последний фрагмент, потому что если длина текста не кратная, она должна быть короче. Чистый, короткий, легкий для понимания... и работает!

    public static string[] Split(this string value, int chunkSize)
    {
        if (string.IsNullOrEmpty(value)) throw new ArgumentException("The string cannot be null.");
        if (chunkSize < 1) throw new ArgumentException("The chunk size should be equal or greater than one.");

        int remainder;
        int divResult = Math.DivRem(value.Length, chunkSize, out remainder);

        int numberOfChunks = remainder > 0 ? divResult + 1 : divResult;
        var result = new string[numberOfChunks];

        int i = 0;
        while (i < numberOfChunks - 1)
        {
            result[i] = value.Substring(i * chunkSize, chunkSize);
            i++;
        }

        int lastChunkSize = remainder > 0 ? remainder : chunkSize;
        result[i] = value.Substring(i * chunkSize, lastChunkSize);

        return result;
    }

Ответ 19

List<string> SplitString(int chunk, string input)
{
    List<string> list = new List<string>();
    int cycles = input.Length / chunk;

    if (input.Length % chunk != 0)
        cycles++;

    for (int i = 0; i < cycles; i++)
    {
        try
        {
            list.Add(input.Substring(i * chunk, chunk));
        }
        catch
        {
            list.Add(input.Substring(i * chunk));
        }
    }
    return list;
}

Ответ 20

Я думаю, что это прямой ответ:

public static IEnumerable<string> Split(this string str, int chunkSize)
    {
        if(string.IsNullOrEmpty(str) || chunkSize<1)
            throw new ArgumentException("String can not be null or empty and chunk size should be greater than zero.");
        var chunkCount = str.Length / chunkSize + (str.Length % chunkSize != 0 ? 1 : 0);
        for (var i = 0; i < chunkCount; i++)
        {
            var startIndex = i * chunkSize;
            if (startIndex + chunkSize >= str.Length)
                yield return str.Substring(startIndex);
            else
                yield return str.Substring(startIndex, chunkSize);
        }
    }

И это охватывает крайние случаи.

Ответ 21

Я знаю, что вопрос лет, но вот реализация Rx. Он обрабатывает проблему length % chunkSize != 0 из коробки:

   public static IEnumerable<string> Chunkify(this string input, int size)
        {
            if(size < 1)
                throw new ArgumentException("size must be greater than 0");

            return input.ToCharArray()
                .ToObservable()
                .Buffer(size)            
                .Select(x => new string(x.ToArray()))
                .ToEnumerable();
        }

Ответ 22

Изменено немного, чтобы вернуть части, размер которых не равен chunkSize

public static IEnumerable<string> Split(this string str, int chunkSize)
    {
        var splits = new List<string>();
        if (str.Length < chunkSize) { chunkSize = str.Length; }
        splits.AddRange(Enumerable.Range(0, str.Length / chunkSize).Select(i => str.Substring(i * chunkSize, chunkSize)));
        splits.Add(str.Length % chunkSize > 0 ? str.Substring((str.Length / chunkSize) * chunkSize, str.Length - ((str.Length / chunkSize) * chunkSize)) : string.Empty);
        return (IEnumerable<string>)splits;
    }

Ответ 23

Я немного вырос на решении João. То, что я сделал по-другому, в моем методе, вы можете указать, хотите ли вы вернуть массив с оставшимися символами или хотите ли вы их обрезать, если конечные символы не соответствуют вашей требуемой длине блока, я думаю, что это довольно гибкий и код довольно прямолинейный:

using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace SplitFunction
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "hello, how are you doing today?";
            string[] chunks = SplitIntoChunks(text, 3,false);
            if (chunks != null)
            {
                chunks.ToList().ForEach(e => Console.WriteLine(e));
            }

            Console.ReadKey();
        }

        private static string[] SplitIntoChunks(string text, int chunkSize, bool truncateRemaining)
        {
            string chunk = chunkSize.ToString(); 
            string pattern = truncateRemaining ? ".{" + chunk + "}" : ".{1," + chunk + "}";

            string[] chunks = null;
            if (chunkSize > 0 && !String.IsNullOrEmpty(text))
                chunks = (from Match m in Regex.Matches(text,pattern)select m.Value).ToArray(); 

            return chunks;
        }     
    }
}

Ответ 24

    public static List<string> SplitByMaxLength(this string str)
    {
        List<string> splitString = new List<string>();

        for (int index = 0; index < str.Length; index += MaxLength)
        {
            splitString.Add(str.Substring(index, Math.Min(MaxLength, str.Length - index)));
        }

        return splitString;
    }

Ответ 25

Я не помню, кто дал мне это, но он отлично работает. Я быстро проверил несколько способов разбить Перечислимые типы на группы. Использование будет просто таким...

List<string> Divided = Source3.Chunk(24).Select(Piece => string.Concat<char>(Piece)).ToList();

Код расширения будет выглядеть следующим образом:

#region Chunk Logic
private class ChunkedEnumerable<T> : IEnumerable<T>
{
    class ChildEnumerator : IEnumerator<T>
    {
        ChunkedEnumerable<T> parent;
        int position;
        bool done = false;
        T current;


        public ChildEnumerator(ChunkedEnumerable<T> parent)
        {
            this.parent = parent;
            position = -1;
            parent.wrapper.AddRef();
        }

        public T Current
        {
            get
            {
                if (position == -1 || done)
                {
                    throw new InvalidOperationException();
                }
                return current;

            }
        }

        public void Dispose()
        {
            if (!done)
            {
                done = true;
                parent.wrapper.RemoveRef();
            }
        }

        object System.Collections.IEnumerator.Current
        {
            get { return Current; }
        }

        public bool MoveNext()
        {
            position++;

            if (position + 1 > parent.chunkSize)
            {
                done = true;
            }

            if (!done)
            {
                done = !parent.wrapper.Get(position + parent.start, out current);
            }

            return !done;

        }

        public void Reset()
        {
            // per http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx
            throw new NotSupportedException();
        }
    }

    EnumeratorWrapper<T> wrapper;
    int chunkSize;
    int start;

    public ChunkedEnumerable(EnumeratorWrapper<T> wrapper, int chunkSize, int start)
    {
        this.wrapper = wrapper;
        this.chunkSize = chunkSize;
        this.start = start;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return new ChildEnumerator(this);
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

}
private class EnumeratorWrapper<T>
{
    public EnumeratorWrapper(IEnumerable<T> source)
    {
        SourceEumerable = source;
    }
    IEnumerable<T> SourceEumerable { get; set; }

    Enumeration currentEnumeration;

    class Enumeration
    {
        public IEnumerator<T> Source { get; set; }
        public int Position { get; set; }
        public bool AtEnd { get; set; }
    }

    public bool Get(int pos, out T item)
    {

        if (currentEnumeration != null && currentEnumeration.Position > pos)
        {
            currentEnumeration.Source.Dispose();
            currentEnumeration = null;
        }

        if (currentEnumeration == null)
        {
            currentEnumeration = new Enumeration { Position = -1, Source = SourceEumerable.GetEnumerator(), AtEnd = false };
        }

        item = default(T);
        if (currentEnumeration.AtEnd)
        {
            return false;
        }

        while (currentEnumeration.Position < pos)
        {
            currentEnumeration.AtEnd = !currentEnumeration.Source.MoveNext();
            currentEnumeration.Position++;

            if (currentEnumeration.AtEnd)
            {
                return false;
            }

        }

        item = currentEnumeration.Source.Current;

        return true;
    }

    int refs = 0;

    // needed for dispose semantics 
    public void AddRef()
    {
        refs++;
    }

    public void RemoveRef()
    {
        refs--;
        if (refs == 0 && currentEnumeration != null)
        {
            var copy = currentEnumeration;
            currentEnumeration = null;
            copy.Source.Dispose();
        }
    }
}
/// <summary>Speed Checked.  Works Great!</summary>
public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, int chunksize)
{
    if (chunksize < 1) throw new InvalidOperationException();

    var wrapper = new EnumeratorWrapper<T>(source);

    int currentPos = 0;
    T ignore;
    try
    {
        wrapper.AddRef();
        while (wrapper.Get(currentPos, out ignore))
        {
            yield return new ChunkedEnumerable<T>(wrapper, chunksize, currentPos);
            currentPos += chunksize;
        }
    }
    finally
    {
        wrapper.RemoveRef();
    }
}
#endregion

Ответ 26

class StringHelper
{
    static void Main(string[] args)
    {
        string str = "Hi my name is vikas bansal and my email id is [email protected]";
        int offSet = 10;

        List<string> chunks = chunkMyStr(str, offSet);

        Console.Read();
    }

    static List<string> chunkMyStr(string str, int offSet)
    {


        List<string> resultChunks = new List<string>();

        for (int i = 0; i < str.Length; i += offSet)
        {
            string temp = str.Substring(i, (str.Length - i) > offSet ? offSet : (str.Length - i));
            Console.WriteLine(temp);
            resultChunks.Add(temp);


        }

        return resultChunks;
    }
}

Ответ 27

Изменено (теперь оно принимает любое не пустое string и любое положительное chunkSize) решение Константина Спирина:

public static IEnumerable<String> Split(String value, int chunkSize) {
  if (null == value)
    throw new ArgumentNullException("value");
  else if (chunkSize <= 0)
    throw new ArgumentOutOfRangeException("chunkSize", "Chunk size should be positive");

  return Enumerable
    .Range(0, value.Length / chunkSize + ((value.Length % chunkSize) == 0 ? 0 : 1))
    .Select(index => (index + 1) * chunkSize < value.Length 
      ? value.Substring(index * chunkSize, chunkSize)
      : value.Substring(index * chunkSize));
}

Тесты:

  String source = @"ABCDEF";

  // "ABCD,EF"
  String test1 = String.Join(",", Split(source, 4));
  // "AB,CD,EF"
  String test2 = String.Join(",", Split(source, 2));
  // "ABCDEF"
  String test3 = String.Join(",", Split(source, 123));

Ответ 28

Основываясь на других плакатных ответах, наряду с некоторыми примерами использования:

public static string FormatSortCode(string sortCode)
{
    return ChunkString(sortCode, 2, "-");
}
public static string FormatIBAN(string iban)
{
    return ChunkString(iban, 4, "&nbsp;&nbsp;");
}

private static string ChunkString(string str, int chunkSize, string separator)
{
    var b = new StringBuilder();
    var stringLength = str.Length;
    for (var i = 0; i < stringLength; i += chunkSize)
    {
        if (i + chunkSize > stringLength) chunkSize = stringLength - i;
        b.Append(str.Substring(i, chunkSize));
        if (i+chunkSize != stringLength)
            b.Append(separator);
    }
    return b.ToString();
}

Ответ 29

Использование расширений буфера из библиотека IX

    static IEnumerable<string> Split( this string str, int chunkSize )
    {
        return str.Buffer(chunkSize).Select(l => String.Concat(l));
    }

Ответ 30

Это можно сделать так же

        string actualString = "1111222233334444";
        var listResult = new List<string>();
        int groupingLength = actualString.Length % 4;
        if (groupingLength > 0)
            listResult.Add(actualString.Substring(0, groupingLength));
        for (int i = groupingLength; i < actualString.Length; i += 4)
        {
            listResult.Add(actualString.Substring(i, 4));
        }

        foreach(var res in listResult)
        {
            Console.WriteLine(res);
        }
        Console.Read();