假设我有一个字符串:
如何将这个字符串分成指定大小的块?
例如,将其分成大小为4的块将返回字符串:
string str = "1111222233334444";
如何将这个字符串分成指定大小的块?
例如,将其分成大小为4的块将返回字符串:
"1111"
"2222"
"3333"
"4444"
string str = "1111222233334444";
"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>();
。 - Drew Spickesstr.Length / chunkSize
更改为double length = str.Length; double size = chunkSize; int count = (int)Math.Ceiling(length/size); return Enumerable.Range(0, count)...
。 - gapstatic 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));
}
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();
str = "1111222233334444";
for (int i = 0; i < stringLength; i += chunkSize)
{
Console.WriteLine(str.Substring(i, chunkSize));
}
int chunkSize = 4
移到循环外面。它只会在最后一次通过时被修改。 - John Feminellai += chunkSize
。 - Ian Kempstr.Length
从循环中提取出来,放到一个局部变量中。C# 优化器可能能够内联数组长度,但我认为按照现有的代码会在每次循环中进行一次方法调用,这不是很高效,因为 str
的大小永远不会改变。 - Daniel Prydenpublic 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... }
- NyergudsIEnumerable
强制转换为数组,尤其不是隐式地。 - NyergudsList<string> groups = (from Match m in Regex.Matches(str, @"\d{4}")
select m.Value).ToList();
\d
字符类替换为.
,并指定RegexOptions.Singleline
。 - Eamon Nerbonne从 .NET 6 开始,我们还可以使用 Chunk
方法:
var result = str
.Chunk(4)
.Select(x => new string(x))
.ToList();
List<string> result = new List<string>(Regex.Split(target, @"(?<=\G.{4})", RegexOptions.Singleline));
target.Length % ChunckSize == 0
,则会返回一个额外的空行,例如 List<string> result = new List<string>(Regex.Split("fooo", @"(?<=\G.{4})", RegexOptions.Singleline));
。 - fubo虽然不太美观也不快,但它可以工作,只需要一行代码就能实现,而且还具有LINQ的特点:
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();
string
是IEnumerable<char>
,因此ToCharArray
是不必要的。 - juharr最近我在工作中写了一些相关的内容,所以我想把解决这个问题的方法发表出来。作为额外的奖励,这个解决方案的功能提供了一种将字符串反向拆分的方式,并且正如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 > 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;
}
}
}
{str.ToString()}
。你确定你不是想用str.String
吗?我之前也遇到了同样的问题,做了这个改变后,一切正常了。 - gunr2171这将比使用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);
}