Предположим, у меня была строка:
string str = "1111222233334444";
Как я могу разбить эту строку на куски некоторого размера?
например, разбив это на размеры 4 вернет строки:
"1111"
"2222"
"3333"
"4444"
Предположим, у меня была строка:
string str = "1111222233334444";
Как я могу разбить эту строку на куски некоторого размера?
например, разбив это на размеры 4 вернет строки:
"1111"
"2222"
"3333"
"4444"
Ответы:
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и т. Д.). Исходный вопрос не определяет никаких требований для этих крайних случаев, и в реальной жизни требования могут отличаться, поэтому они выходят за рамки этого ответа.
(i * chunkSize + chunkSize <= str.Length) ? chunkSize : str.Length - i * chunkSize. Дополнительная проблема заключается в том, что эта функция не учитывает нулевую переменную str. Это может быть исправлено путем оборачивать все о возвращенном в другом тройном выражении: (str != null) ? ... : Enumerable.Empty<String>();.
str.Length / chunkSizeдоdouble length = str.Length; double size = chunkSize; int count = (int)Math.Ceiling(length/size); return Enumerable.Range(0, count)...
StringLength % 4 will always be 0. Если Linqэто не так легко понять, то есть другие ответы, которые используют циклы и выходы. Любой может свободно выбрать решение, которое ему нравится больше всего. Вы можете опубликовать свой код как ответ, и люди с радостью проголосуют за него.
В сочетании голубь + ответы Константина ...
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));
}
Однако ОП явно заявил, что ему это не нужно; это немного длиннее и труднее читать, немного медленнее. В духе KISS и YAGNI я бы выбрал первый вариант: возможно, это наиболее эффективная реализация, и она очень короткая, удобочитаемая и, что важно, создает исключение для несоответствующего ввода.
Почему не петли? Вот кое-что, что сделало бы это довольно хорошо:
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, но не говорите, что ваша идея невозможна, просто задаетесь вопросом о мотивации этого, если простой цикл for делает это очень хорошо? Очевидно, что вышеупомянутое можно очистить и даже добавить в качестве метода расширения.
Или, как упоминалось в комментариях, вы знаете, что это / 4 тогда
str = "1111222233334444";
for (int i = 0; i < stringLength; i += chunkSize)
{Console.WriteLine(str.Substring(i, chunkSize));}
int chunkSize = 4за пределы петли. Он будет изменен только на последнем проходе.
i += chunkSizeвместо этого.
str.Lengthиз цикла в локальную переменную. Оптимизатор C # может быть в состоянии встроить длину массива, но я думаю, что написанный код будет выполнять вызов метода в каждом цикле, что неэффективно, поскольку размер strникогда не изменяется.
Используя регулярные выражения и Linq :
List<string> groups = (from Match m in Regex.Matches(str, @"\d{4}")
select m.Value).ToList();
Я считаю это более читабельным, но это просто личное мнение. Это также может быть однострочник :).
\dкласс символов на .и указать RegexOptions.Singleline.
Это основано на решении @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
Модульные тесты удалены для краткости (см. Предыдущую версию )
if (str.Length == 0) yield return String.Empty; else { for... }
IEnumerableк массиву, особенно неявно.
Chunkify... Это не мое, я не помню, где я видел это имя, но мне было очень приятно
Как это для однострочника?
List<string> result = new List<string>(Regex.Split(target, @"(?<=\G.{4})", RegexOptions.Singleline));
С этим регулярным выражением не имеет значения, если последний кусок меньше четырех символов, потому что он только когда-либо смотрит на символы позади него.
Я уверен, что это не самое эффективное решение, но мне просто нужно было его выбросить.
target.Lenght % ChunckSize == 0этого возвращает дополнительную пустую строку, напримерList<string> result = new List<string>(Regex.Split("fooo", @"(?<=\G.{4})", RegexOptions.Singleline));
Это не красиво и не быстро, но работает, это одна строка и это 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();
ToCharArrayненужно, так как stringесть IEnumerable<char>.
Недавно мне пришлось написать что-то, что выполняет это на работе, поэтому я подумал, что опубликую свое решение этой проблемы. В качестве дополнительного бонуса, функциональность этого решения обеспечивает способ разделения строки в противоположном направлении, и он правильно обрабатывает символы Юникода, как ранее упоминал Марвин Пинто выше. Итак, вот оно:
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 > 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 < 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
{str.ToString()}в конце вашего первого заявления IF. Вы уверены, что не имели в виду str.String? У меня была проблема с кодом выше, я сделал это изменение, и все заработало.
Это должно быть намного быстрее и эффективнее, чем использование 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);
}
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;
}
Вы можете использовать morelinq от Jon Skeet. Используйте Пакет как:
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
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));
}
}
Шесть лет спустя о_О
Да просто так
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
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).
Важный совет, если чанкованная строка должна поддерживать все символы Юникода.
Если строка должна поддерживать международные символы, такие как 𠀋, то разбейте строку, используя класс System.Globalization.StringInfo. Используя StringInfo, вы можете разделить строку по количеству текстовых элементов.
string internationalString = '𠀋';
Вышеуказанная строка имеет длину 2, потому что String.Lengthсвойство возвращает количество объектов Char в этом случае, а не количество символов Unicode.
Лучший, самый простой и общий ответ :).
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))));
}
Substringперегрузку, которая не требует параметра длины originalString.Substring(i). Также вы можете использовать >вместо >=вашего чека.
Лично я предпочитаю свое решение :-)
Он обрабатывает:
Он реализован как метод расширения и рассчитывает количество порций, которые будут сгенерированы заранее. Он проверяет последний фрагмент, потому что, если длина текста не кратна, он должен быть короче. Чисто, коротко, легко понять ... и работает!
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;
}
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;
}
Я думаю, что это прямой ответ:
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);
}
}
И это охватывает крайние случаи.
Я знаю, что вопрос лет, но вот реализация 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();
}
Я немного развил решение Жуана. Что я сделал по-другому, так это то, что в моем методе вы можете указать, хотите ли вы возвращать массив с оставшимися символами или вы хотите обрезать их, если конечные символы не соответствуют требуемой длине порции, я думаю, что это довольно гибко и Код довольно прост:
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;
}
}
}
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;
}
Немного изменен, чтобы вернуть части, размер которых не равен 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;
}
Listк этому IEnumerable; все, что делает, это скрывает специфичные для List функции, которые вы, возможно, захотите использовать. Нет никаких недостатков в том, чтобы просто вернуть List.
Я не могу вспомнить, кто дал мне это, но это прекрасно работает. Я быстро протестировал несколько способов разбить перечислимые типы на группы. Использование будет просто так ...
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
class StringHelper
{
static void Main(string[] args)
{
string str = "Hi my name is vikas bansal and my email id is bansal.vks@gmail.com";
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;
}
}
i += offSetв свое forвыражение.
Модифицированный (теперь он принимает любое ненулевое 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));
static List<string> GetChunks(string value, int chunkLength)
{
var res = new List<string>();
int count = (value.Length / chunkLength) + (value.Length % chunkLength > 0 ? 1 : 0);
Enumerable.Range(0, count).ToList().ForEach(f => res.Add(value.Skip(f * chunkLength).Take(chunkLength).Select(z => z.ToString()).Aggregate((a,b) => a+b)));
return res;
}
На основе ответов других постеров, а также некоторые примеры использования:
public static string FormatSortCode(string sortCode)
{
return ChunkString(sortCode, 2, "-");
}
public static string FormatIBAN(string iban)
{
return ChunkString(iban, 4, " ");
}
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();
}
Использование расширений буфера из библиотеки IX
static IEnumerable<string> Split( this string str, int chunkSize )
{
return str.Buffer(chunkSize).Select(l => String.Concat(l));
}