Зачем использовать LINQ или регулярные выражения, когда стандартные функции C # для работы со строками могут делать это с меньшими усилиями и большей скоростью? Кроме того, что произойдет, если длина строки будет нечетным числом символов?
Ян Кемп
7
«Я бы хотел избежать петель» - почему?
Митч Уит
12
Использование простого цикла определенно дает лучшую производительность.
Гуффа
4
nichesoftware.co.nz/blog/200909/linq-vs-loop-performance - это довольно хорошее сравнение между linq и фактическим циклом над массивом. Я сомневаюсь, что вы когда-нибудь найдете linq быстрее, чем написанный вручную код, потому что он продолжает вызывать делегаты времени выполнения, которые трудно оптимизировать. Linq более веселый, хотя :)
Blindy
2
Используете ли вы LINQ или регулярные выражения, цикл все еще там.
Обратите внимание, что для изящной обработки краевых случаев может потребоваться дополнительный код ( nullили пустая входная строка chunkSize == 0, длина входной строки, не делимая на chunkSizeи т. Д.). Исходный вопрос не определяет никаких требований для этих крайних случаев, и в реальной жизни требования могут отличаться, поэтому они выходят за рамки этого ответа.
@ Гарри, хороший улов! Это можно исправить с помощью вставного троичного выражения в параметре count подстроки. Что - то вроде: (i * chunkSize + chunkSize <= str.Length) ? chunkSize : str.Length - i * chunkSize. Дополнительная проблема заключается в том, что эта функция не учитывает нулевую переменную str. Это может быть исправлено путем оборачивать все о возвращенном в другом тройном выражении: (str != null) ? ... : Enumerable.Empty<String>();.
Дрю Спикс
7
Это было близко, но в отличие от предыдущих 30 upvoters, я должен был изменить ограничение на количество петель в диапазоне от str.Length / chunkSizeдоdouble length = str.Length; double size = chunkSize; int count = (int)Math.Ceiling(length/size); return Enumerable.Range(0, count)...
щели
4
@KonstantinSpirin Я согласен, если код работал. Он обрабатывает только случай, когда строка кратна chunkSize, остальная часть строки теряется. Пожалуйста, исправьте. Также имейте в виду, что LINQ и его волшебство не так легко понять тому, кто просто хочет найти решение этой проблемы. Теперь человек должен понимать, что делают функции Enumerable.Range () и .Select (). Я не буду спорить, что вы должны понимать, как писать код на C # / .NET, поскольку эти функции были в BCL уже много лет.
CodeMonkeyKing
6
Автор темы сказал в комментариях, что StringLength % 4 will always be 0. Если Linqэто не так легко понять, то есть другие ответы, которые используют циклы и выходы. Любой может свободно выбрать решение, которое ему нравится больше всего. Вы можете опубликовать свой код как ответ, и люди с радостью проголосуют за него.
Константин Спирин
3
Enumerable.Range (0, (str.Length + chunkSize - 1) / chunkSize) .Select (i => str.Substring (i * chunkSize, Math.Min (str.Length - i * chunkSize, chunkSize)))
Стен Петров
135
В сочетании голубь + ответы Константина ...
staticIEnumerable<string>WholeChunks(string str,int chunkSize){for(int i =0; i < str.Length; i += chunkSize)yieldreturn str.Substring(i, chunkSize);}
Это будет работать для всех строк, которые могут быть разбиты на целое число фрагментов, и в противном случае будет выдано исключение.
Если вы хотите поддерживать строки любой длины, вы можете использовать следующий код:
staticIEnumerable<string>ChunksUpto(string str,int maxChunkSize){for(int i =0; i < str.Length; i += maxChunkSize)yieldreturn str.Substring(i,Math.Min(maxChunkSize, str.Length-i));}
Однако ОП явно заявил, что ему это не нужно; это немного длиннее и труднее читать, немного медленнее. В духе KISS и YAGNI я бы выбрал первый вариант: возможно, это наиболее эффективная реализация, и она очень короткая, удобочитаемая и, что важно, создает исключение для несоответствующего ввода.
+1 стоит кивнуть. вроде бьет по голове гвоздем. он ищет краткий ситнакс, и вы также даете (вероятно) лучшую производительность.
голубь
7
И если вы сделаете это "статическим ... Chunk (эта строка str, int chunkSize) {" у вас даже есть еще одна "новая" особенность C #. Затем вы можете написать «1111222233334444» .Chunk (4).
MartinStettner
1
@MartinStettner: Это, безусловно, неплохая идея, если это обычная операция.
Имон Нербонн
Вы должны включить только последний код. Первый требует, чтобы вы понимали и проверяли, чтобы строка была кратна размеру куска перед использованием, или понимали, что она не вернет остаток строки.
CodeMonkeyKing
Вопрос ОП не дает понять, нужна ли ему эта функциональность. Первое решение проще, быстрее и надежно дает сбой, за исключением случаев, когда строка не может быть равномерно разбита на указанный размер фрагмента. Я согласен, что возвращать «неправильные» результаты было бы плохо, но это не то, что он делает - это просто вызывает исключение, так что я бы согласился с его использованием, если вы можете жить с ограничением.
Имон Нербонн
56
Почему не петли? Вот кое-что, что сделало бы это довольно хорошо:
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за пределы петли. Он будет изменен только на последнем проходе.
Джон Феминелла
+1 за простое и эффективное решение - это то, как я бы это сделал, хотя я бы использовал i += chunkSizeвместо этого.
Ян Кемп
Вероятно, незначительный спор, но вы также должны вытащить str.Lengthиз цикла в локальную переменную. Оптимизатор C # может быть в состоянии встроить длину массива, но я думаю, что написанный код будет выполнять вызов метода в каждом цикле, что неэффективно, поскольку размер strникогда не изменяется.
Даниэль Приден
@ Даниэль, вставь свою идею туда. хотя я не уверен, что это не будет рассчитано во время выполнения, но это другой вопрос;)
dove
@Daniel, возвращаясь к этому, уверен, что эта оптимизация будет извлечена компилятором.
голубь
41
Используя регулярные выражения и Linq :
List<string> groups =(fromMatch m inRegex.Matches(str,@"\d{4}")select m.Value).ToList();
Я считаю это более читабельным, но это просто личное мнение. Это также может быть однострочник :).
Измените шаблон на @ "\ d {1,4}", и он работает для любой длины строки. :)
Guffa
3
+1 Хотя это медленнее других решений, оно определенно очень читабельно. Мне не ясно, нужны ли для ОП цифры или произвольные символы; вероятно, было бы целесообразно заменить \dкласс символов на .и указать RegexOptions.Singleline.
Имон Нербонн
2
или просто Regex.Matches (s, @ "\ d {1,4}"). Select (m => m.Value) .ToList (); Я никогда не понимал смысл этого альтернативного синтаксиса, который служит только для того, чтобы скрыть, что мы используем методы расширения.
Даг
38
Это основано на решении @dove, но реализовано как метод расширения.
Преимущества:
Метод расширения
Крышки угловые
Разбивает строку на любые символы: цифры, буквы, другие символы
Код
publicstaticclassEnumerableEx{publicstaticIEnumerable<string>SplitBy(thisstring str,int chunkLength){if(String.IsNullOrEmpty(str))thrownewArgumentException();if(chunkLength <1)thrownewArgumentException();for(int i =0; i < str.Length; i += chunkLength){if(chunkLength + i > str.Length)
chunkLength = str.Length- i;yieldreturn str.Substring(i, chunkLength);}}}
использование
var result ="bobjoecat".SplitBy(3);// bob, joe, cat
Интересное решение, но во избежание проверок на входе, выходящих за пределы нуля, кажется более логичным позволить пустой строке просто возвращать одну пустую строку:if (str.Length == 0) yield return String.Empty; else { for... }
Nyerguds
Я имею в виду, что именно так обычный String.Split обрабатывает пустые строки; он возвращает одну запись пустой строки.
Nyerguds
Примечание: ваш пример использования неверен. Вы не можете просто привести IEnumerableк массиву, особенно неявно.
Nyerguds
Лично мне нравится называть этот метод Chunkify... Это не мое, я не помню, где я видел это имя, но мне было очень приятно
quetzalcoatl
20
Как это для однострочника?
List<string> result =newList<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));
fubo
9
Это не красиво и не быстро, но работает, это одна строка и это LINQy:
List<string> a = text.Select((c, i)=>new{Char= c,Index= i }).GroupBy(o => o.Index/4).Select(g =>newString(g.Select(o => o.Char).ToArray())).ToList();
Гарантируется ли, что GroupBy сохраняет порядок элементов?
Константин Спирин
ToCharArrayненужно, так как stringесть IEnumerable<char>.
juharr
8
Недавно мне пришлось написать что-то, что выполняет это на работе, поэтому я подумал, что опубликую свое решение этой проблемы. В качестве дополнительного бонуса, функциональность этого решения обеспечивает способ разделения строки в противоположном направлении, и он правильно обрабатывает символы Юникода, как ранее упоминал Марвин Пинто выше. Итак, вот оно:
using System;
using Extensions;
namespace TestCSharp{classProgram{staticvoidMain(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{publicstaticclassStringExtensions{/// <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> publicstaticstring[]Split(thisstring s,int length){System.Globalization.StringInfo str =newSystem.Globalization.StringInfo(s);int lengthAbs =Math.Abs(length);if(str ==null|| str.LengthInTextElements==0|| lengthAbs ==0|| str.LengthInTextElements<= lengthAbs)returnnewstring[]{ str.ToString()};string[]array=newstring[(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));returnarray;}}}
Я заметил проблему с этим кодом. У вас есть {str.ToString()}в конце вашего первого заявления IF. Вы уверены, что не имели в виду str.String? У меня была проблема с кодом выше, я сделал это изменение, и все заработало.
gunr2171
@ gunr2171 Похоже, что если str == null, эта строка также выдаст исключение NullReferenceException.
Джон Заброски
5
Это должно быть намного быстрее и эффективнее, чем использование LINQ или других подходов, используемых здесь.
publicstaticIEnumerable<string>Splice(thisstring s,int spliceLength){if(s ==null)thrownewArgumentNullException("s");if(spliceLength <1)thrownewArgumentOutOfRangeException("spliceLength");if(s.Length==0)yieldbreak;var start =0;for(var end = spliceLength; end < s.Length; end += spliceLength){yieldreturn s.Substring(start, spliceLength);
start = end;}yieldreturn s.Substring(start);}
Это похоже на раннюю проверку, но это не так. Вы не получите ошибку, пока не начнете перечислять перечислимые. Вам нужно разбить вашу функцию на две части, где первая часть выполняет проверку аргументов, а затем возвращает результаты второй, закрытой части, которая выполняет перечисление.
ErikE
4
publicstaticIEnumerable<IEnumerable<T>>SplitEvery<T>(thisIEnumerable<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>>();}publicstaticIEnumerable<T>Cons<T>(T x,IEnumerable<T> xs){yieldreturn x;foreach(var xi in xs)yieldreturn xi;}
Это вернет 4 фрагмента для строки "1111222233334444". Если длина строки меньше или равна размеру куска Batch, строка вернется как единственный элементIEnumerable<string>
Для вывода:
foreach(var chunk in chunks){Console.WriteLine(chunk);}
using System;
using System.Collections.Generic;
using System.Linq;publicclassProgram{publicstaticvoidMain(){var x ="Hello World";foreach(var i in x.ChunkString(2))Console.WriteLine(i);}}publicstaticclassExt{publicstaticIEnumerable<string>ChunkString(thisstring 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));}}
Console.WriteLine(string.Join(" ","abc".Split(2,false)));// ab cConsole.WriteLine(string.Join(" ","abc".Split(2,true)));// a bcConsole.WriteLine(string.Join(" ","a".Split(2,true)));// aConsole.WriteLine(string.Join(" ","a".Split(2,false)));// a
А как насчет крайнего случая «input is a empty string»? Я ожидаю, что, как и в случае с Split, вернуть IEnumerable с единственной пустой строкой, содержащей запись.
Nyerguds
3
Просто и коротко:
// this means match a space or not a space (anything) up to 4 charactersvar lines =Regex.Matches(str,@"[\s\S]{0,4}").Cast<Match>().Select(x => x.Value);
Важный совет, если чанкованная строка должна поддерживать все символы Юникода.
Если строка должна поддерживать международные символы, такие как 𠀋, то разбейте строку, используя класс System.Globalization.StringInfo. Используя StringInfo, вы можете разделить строку по количеству текстовых элементов.
string internationalString ='𠀋';
Вышеуказанная строка имеет длину 2, потому что String.Lengthсвойство возвращает количество объектов Char в этом случае, а не количество символов Unicode.
string originalString ="1111222233334444";List<string> test =newList<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). Также вы можете использовать >вместо >=вашего чека.
Расил Хилан
@RacilHilan Я проверю изменения кода с вашим предложением и обновлю ответ. Я рад, что кто-то с такой хорошей репутацией получил время пересмотреть мой код. :) Спасибо, Сандип
Sandeep Kushwah
2
Лично я предпочитаю свое решение :-)
Он обрабатывает:
Длина строки, кратная размеру куска.
Длина строки НЕ кратна размеру куска.
Длина строки меньше размера чанка.
NULL и пустые строки (выдает исключение).
Размеры чанка меньше 1 (исключение).
Он реализован как метод расширения и рассчитывает количество порций, которые будут сгенерированы заранее. Он проверяет последний фрагмент, потому что, если длина текста не кратна, он должен быть короче. Чисто, коротко, легко понять ... и работает!
publicstaticstring[]Split(thisstringvalue,int chunkSize){if(string.IsNullOrEmpty(value))thrownewArgumentException("The string cannot be null.");if(chunkSize <1)thrownewArgumentException("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 =newstring[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;}
Мне очень нравится этот ответ, но, возможно, вам следует использовать if ((i + 1) * chunk> = input.Length) вместо try / catch, поскольку исключения предназначены для исключительных случаев.
nelsontruran
2
Я думаю, что это прямой ответ:
publicstaticIEnumerable<string>Split(thisstring str,int chunkSize){if(string.IsNullOrEmpty(str)|| chunkSize<1)thrownewArgumentException("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)yieldreturn str.Substring(startIndex);elseyieldreturn str.Substring(startIndex, chunkSize);}}
Я знаю, что вопрос лет, но вот реализация Rx. Это решает length % chunkSize != 0проблему из коробки:
publicstaticIEnumerable<string>Chunkify(thisstring input,int size){if(size <1)thrownewArgumentException("size must be greater than 0");return input.ToCharArray().ToObservable().Buffer(size).Select(x =>newstring(x.ToArray())).ToEnumerable();}
Я немного развил решение Жуана. Что я сделал по-другому, так это то, что в моем методе вы можете указать, хотите ли вы возвращать массив с оставшимися символами или вы хотите обрезать их, если конечные символы не соответствуют требуемой длине порции, я думаю, что это довольно гибко и Код довольно прост:
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace SplitFunction{classProgram{staticvoidMain(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();}privatestaticstring[]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 =(fromMatch m inRegex.Matches(text,pattern)select m.Value).ToArray();return chunks;}}}
publicstaticList<string>SplitByMaxLength(thisstring str){List<string> splitString =newList<string>();for(int index =0; index < str.Length; index +=MaxLength){
splitString.Add(str.Substring(index,Math.Min(MaxLength, str.Length- index)));}return splitString;}
Не уверен, что вижу применение обратного приведения Listк этому IEnumerable; все, что делает, это скрывает специфичные для List функции, которые вы, возможно, захотите использовать. Нет никаких недостатков в том, чтобы просто вернуть List.
Nyerguds
1
Я не могу вспомнить, кто дал мне это, но это прекрасно работает. Я быстро протестировал несколько способов разбить перечислимые типы на группы. Использование будет просто так ...
classStringHelper{staticvoidMain(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();}staticList<string> chunkMyStr(string str,int offSet){List<string> resultChunks =newList<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;}}
Ответы:
Обратите внимание, что для изящной обработки краевых случаев может потребоваться дополнительный код (
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
это не так легко понять, то есть другие ответы, которые используют циклы и выходы. Любой может свободно выбрать решение, которое ему нравится больше всего. Вы можете опубликовать свой код как ответ, и люди с радостью проголосуют за него.В сочетании голубь + ответы Константина ...
Это будет работать для всех строк, которые могут быть разбиты на целое число фрагментов, и в противном случае будет выдано исключение.
Если вы хотите поддерживать строки любой длины, вы можете использовать следующий код:
Однако ОП явно заявил, что ему это не нужно; это немного длиннее и труднее читать, немного медленнее. В духе KISS и YAGNI я бы выбрал первый вариант: возможно, это наиболее эффективная реализация, и она очень короткая, удобочитаемая и, что важно, создает исключение для несоответствующего ввода.
источник
Почему не петли? Вот кое-что, что сделало бы это довольно хорошо:
Я не знаю, как бы вы справились со случаем, когда строка не имеет множителя 4, но не говорите, что ваша идея невозможна, просто задаетесь вопросом о мотивации этого, если простой цикл for делает это очень хорошо? Очевидно, что вышеупомянутое можно очистить и даже добавить в качестве метода расширения.
Или, как упоминалось в комментариях, вы знаете, что это / 4 тогда
источник
int chunkSize = 4
за пределы петли. Он будет изменен только на последнем проходе.i += chunkSize
вместо этого.str.Length
из цикла в локальную переменную. Оптимизатор C # может быть в состоянии встроить длину массива, но я думаю, что написанный код будет выполнять вызов метода в каждом цикле, что неэффективно, поскольку размерstr
никогда не изменяется.Используя регулярные выражения и Linq :
Я считаю это более читабельным, но это просто личное мнение. Это также может быть однострочник :).
источник
\d
класс символов на.
и указатьRegexOptions.Singleline
.Это основано на решении @dove, но реализовано как метод расширения.
Преимущества:
Код
использование
Модульные тесты удалены для краткости (см. Предыдущую версию )
источник
if (str.Length == 0) yield return String.Empty; else { for... }
IEnumerable
к массиву, особенно неявно.Chunkify
... Это не мое, я не помню, где я видел это имя, но мне было очень приятноКак это для однострочника?
С этим регулярным выражением не имеет значения, если последний кусок меньше четырех символов, потому что он только когда-либо смотрит на символы позади него.
Я уверен, что это не самое эффективное решение, но мне просто нужно было его выбросить.
источник
target.Lenght % ChunckSize == 0
этого возвращает дополнительную пустую строку, напримерList<string> result = new List<string>(Regex.Split("fooo", @"(?<=\G.{4})", RegexOptions.Singleline));
Это не красиво и не быстро, но работает, это одна строка и это LINQy:
источник
ToCharArray
ненужно, так какstring
естьIEnumerable<char>
.Недавно мне пришлось написать что-то, что выполняет это на работе, поэтому я подумал, что опубликую свое решение этой проблемы. В качестве дополнительного бонуса, функциональность этого решения обеспечивает способ разделения строки в противоположном направлении, и он правильно обрабатывает символы Юникода, как ранее упоминал Марвин Пинто выше. Итак, вот оно:
Кроме того, вот ссылка на изображение с результатами выполнения этого кода: http://i.imgur.com/16Iih.png
источник
{str.ToString()}
в конце вашего первого заявления IF. Вы уверены, что не имели в видуstr.String
? У меня была проблема с кодом выше, я сделал это изменение, и все заработало.Это должно быть намного быстрее и эффективнее, чем использование LINQ или других подходов, используемых здесь.
источник
источник
Вы можете использовать morelinq от Jon Skeet. Используйте Пакет как:
Это вернет 4 фрагмента для строки
"1111222233334444"
. Если длина строки меньше или равна размеру кускаBatch
, строка вернется как единственный элементIEnumerable<string>
Для вывода:
и это даст:
источник
и другой подход:
источник
Шесть лет спустя о_О
Да просто так
или
AFAIK все крайние случаи обрабатываются.
источник
Просто и коротко:
источник
.
?Он правильно обрабатывает длину входной строки, не делимую на chunkSize.
Обратите внимание, что для изящной обработки краевых случаев может потребоваться дополнительный код (пустая или пустая строка ввода, chunkSize == 0).
источник
Важный совет, если чанкованная строка должна поддерживать все символы Юникода.
Если строка должна поддерживать международные символы, такие как
𠀋
, то разбейте строку, используя класс System.Globalization.StringInfo. Используя StringInfo, вы можете разделить строку по количеству текстовых элементов.Вышеуказанная строка имеет длину 2, потому что
String.Length
свойство возвращает количество объектов Char в этом случае, а не количество символов Unicode.источник
Лучший, самый простой и общий ответ :).
источник
Substring
перегрузку, которая не требует параметра длиныoriginalString.Substring(i)
. Также вы можете использовать>
вместо>=
вашего чека.Лично я предпочитаю свое решение :-)
Он обрабатывает:
Он реализован как метод расширения и рассчитывает количество порций, которые будут сгенерированы заранее. Он проверяет последний фрагмент, потому что, если длина текста не кратна, он должен быть короче. Чисто, коротко, легко понять ... и работает!
источник
источник
Я думаю, что это прямой ответ:
И это охватывает крайние случаи.
источник
Я знаю, что вопрос лет, но вот реализация Rx. Это решает
length % chunkSize != 0
проблему из коробки:источник
Я немного развил решение Жуана. Что я сделал по-другому, так это то, что в моем методе вы можете указать, хотите ли вы возвращать массив с оставшимися символами или вы хотите обрезать их, если конечные символы не соответствуют требуемой длине порции, я думаю, что это довольно гибко и Код довольно прост:
источник
источник
Немного изменен, чтобы вернуть части, размер которых не равен chunkSize
источник
List
к этомуIEnumerable
; все, что делает, это скрывает специфичные для List функции, которые вы, возможно, захотите использовать. Нет никаких недостатков в том, чтобы просто вернутьList
.Я не могу вспомнить, кто дал мне это, но это прекрасно работает. Я быстро протестировал несколько способов разбить перечислимые типы на группы. Использование будет просто так ...
Код расширения будет выглядеть следующим образом ...
источник
источник
i += offSet
в своеfor
выражение.Модифицированный (теперь он принимает любое ненулевое
string
и любое положительноеchunkSize
) решение Константина Спирина :тесты:
источник
демонстрация
источник
На основе ответов других постеров, а также некоторые примеры использования:
источник
Использование расширений буфера из библиотеки IX
источник