将字符串分成一定大小的块

假设我有一个字符串:

string str = "1111222233334444";

我如何把这个字符串分成一定大小的块?

例如,将它分解为4的大小将返回字符串:

"1111"
"2222"
"3333"
"4444"
289121 次浏览

为什么不是循环?这里有一些东西可以很好地做到这一点:

        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));}
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整除,等等)。最初的问题没有为这些边缘情况指定任何需求,在现实生活中,需求可能会有所不同,因此它们超出了这个答案的范围。

它不是很漂亮,也不是很快,但它是有效的,它是一行程序,它是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();

使用正则表达式Linq:

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

我觉得这样更有可读性,但这只是个人观点。它也可以是一行代码:)。

在多芬和康他汀的答案组合中……

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的精神,我选择第一个选项:它可能是最有效的实现,而且非常简短、可读,而且重要的是,它会对不符合规范的输入抛出异常。

这样写一行代码怎么样?

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

对于这个正则表达式,最后一个块是否小于4个字符并不重要,因为它只查看它后面的字符。

我知道这不是最有效的解决方案,但我不得不把它扔出去。

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

稍微更改为返回大小不等于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;
}

这应该比使用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);
}

如果要分块的字符串需要支持所有Unicode字符,有一个重要提示。

如果字符串要支持像𠀋这样的国际字符,则使用System.Globalization.StringInfo类拆分字符串。使用StringInfo,可以根据文本元素的数量拆分字符串。

string internationalString = '𠀋';

上面的字符串长度为2,因为String.Length属性在这个实例中返回Char对象的数量,而不是Unicode字符的数量。

这是基于@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

为了简洁起见,删除了单元测试(参见先前的版本)

最近我不得不在工作中写一些东西来完成这个任务,所以我想我会把我对这个问题的解决方案贴出来。作为一个额外的好处,这个解决方案的功能提供了一种方法,以相反的方向分割字符串,并且它正确地处理上面Marvin Pinto提到的unicode字符。所以,就是这样:

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

我已经稍微建立了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;
}
}
}
    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;
}

我不记得是谁给我的了,但它很好用。我快速测试了几种将枚举类型分成组的方法。用法是这样的…

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

根据其他帖子的答案,以及一些使用示例:

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

使用第九图书馆中的Buffer扩展

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

你可以使用Jon Skeet的morelinq。像这样使用批处理:

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

这将返回字符串"1111222233334444"的4个块。如果字符串长度小于或等于块大小,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));
}
}

最好,最简单和一般的答案:)。

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

修改(现在它接受任何非空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));

这也可以用这种方式来完成

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

我个人更喜欢我的解决方案:-)

它处理:

  • 是块大小的倍数的字符串长度。
  • 不是块大小倍数的字符串长度。
  • 小于块大小的字符串长度。
  • 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;
}

六年后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

如果需要分割几个不同的长度: 例如,日期和时间的指定格式为stringstrangeStr = "07092016090532"; 07092016090532(日期:07.09.2016时间:09:05:32)

public static IEnumerable<string> SplitBy(this string str, int[] chunkLength)
{
if (String.IsNullOrEmpty(str)) throw new ArgumentException();
int i = 0;
for (int j = 0; j < chunkLength.Length; j++)
{
if (chunkLength[j] < 1) throw new ArgumentException();
if (chunkLength[j] + i > str.Length)
{
chunkLength[j] = str.Length - i;
}
yield return str.Substring(i, chunkLength[j]);
i += chunkLength[j];
}
}

使用:

string[] dt = strangeStr.SplitBy(new int[] { 2, 2, 4, 2, 2, 2, 2 }).ToArray();

简单而简短:

// 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);
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);
}
}

它涵盖了边缘情况。

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整除的输入字符串长度。

请注意,可能需要额外的代码来优雅地处理边缘情况(null或空输入字符串,chunkSize == 0)。

我知道这个问题已经有很多年了,但是这里有一个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();
}
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;
}

demo

以下是我的观点:

  IEnumerable<string> Split(string str, int chunkSize)
{
while (!string.IsNullOrWhiteSpace(str))
{
var chunk = str.Take(chunkSize).ToArray();
str = str.Substring(chunk.Length);
yield return new string(chunk);


}


}//Split
        List<string> chunks = new List<string>();
var longString = new string('s', 3000);
var chunkLength = 1273;
var ratio = (double)longString.Length / chunkLength;
var countOfChunks = Convert.ToByte(Math.Round(ratio, MidpointRounding.ToPositiveInfinity));


for (byte i = 0; i < countOfChunks; i++)
{
var remainingLength = longString.Length - chunkLength * i;
if (chunkLength > remainingLength)
chunks.Add(longString.Substring(i * chunkLength, remainingLength));
else
chunks.Add(longString.Substring(i * chunkLength, chunkLength));
}

我把它提升到了另一个层次。扔掉是一个简单的句子,但在我的情况下,我需要整个单词。我想我应该把它发布出来,以防有人需要类似的东西。

static IEnumerable<string> Split(string orgString, int chunkSize, bool wholeWords = true)
{
if (wholeWords)
{
List<string> result = new List<string>();
StringBuilder sb = new StringBuilder();


if (orgString.Length > chunkSize)
{
string[] newSplit = orgString.Split(' ');
foreach (string str in newSplit)
{
if (sb.Length != 0)
sb.Append(" ");


if (sb.Length + str.Length > chunkSize)
{
result.Add(sb.ToString());
sb.Clear();
}


sb.Append(str);
}


result.Add(sb.ToString());
}
else
result.Add(orgString);


return result;
}
else
return new List<string>(Regex.Split(orgString, @"(?<=\G.{" + chunkSize + "})", RegexOptions.Singleline));
}

基于以下评论的结果:

string msg = "336699AABBCCDDEEFF";
foreach (string newMsg in Split(msg, 2, false))
{
Console.WriteLine($">>{newMsg}<<");
}


Console.ReadKey();

结果:

>>33<<
>>66<<
>>99<<
>>AA<<
>>BB<<
>>CC<<
>>DD<<
>>EE<<
>>FF<<
>><<

另一种说法是:

List<string> splitData = (List<string>)Split(msg, 2, false);


for (int i = 0; i < splitData.Count - 1; i++)
{
Console.WriteLine($">>{splitData[i]}<<");
}


Console.ReadKey();

新结果:

>>33<<
>>66<<
>>99<<
>>AA<<
>>BB<<
>>CC<<
>>DD<<
>>EE<<
>>FF<<
        public static List<string> DevideByStringLength(string text, int chunkSize)
{
double a = (double)text.Length / chunkSize;
var numberOfChunks = Math.Ceiling(a);


Console.WriteLine($"{text.Length} | {numberOfChunks}");


List<string> chunkList = new List<string>();
for (int i = 0; i < numberOfChunks; i++)
{
string subString = string.Empty;
if (i == (numberOfChunks - 1))
{
subString = text.Substring(chunkSize * i, text.Length - chunkSize * i);
chunkList.Add(subString);
continue;
}
subString = text.Substring(chunkSize * i, chunkSize);
chunkList.Add(subString);
}
return chunkList;
}

从。net 6开始,我们还可以使用Chunk方法:

var result = str
.Chunk(4)
.Select(x => new string(x))
.ToList();

试试这个:

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