将string分成长度可变的较小的string

我想通过一定的长度variables来分割一个string。
当string的最后一段长度不能长于或长于长度时,它需要进行边界检查以防止爆炸。 寻找最简洁(但可以理解)的版本。

例:

string x = "AAABBBCC"; string[] arr = x.SplitByLength(3); // arr[0] -> "AAA"; // arr[1] -> "BBB"; // arr[2] -> "CC" 

你需要使用一个循环:

 public static IEnumerable<string> SplitByLength(this string str, int maxLength) { for (int index = 0; index < str.Length; index += maxLength) { yield return str.Substring(index, Math.Min(maxLength, str.Length - index)); } } 

替代scheme:

 public static IEnumerable<string> SplitByLength(this string str, int maxLength) { int index = 0; while(true) { if (index + maxLength >= str.Length) { yield return str.Substring(index); yield break; } yield return str.Substring(index, maxLength); index += maxLength; } } 

第二种替代方法:(对于那些不能忍受while(true)

 public static IEnumerable<string> SplitByLength(this string str, int maxLength) { int index = 0; while(index + maxLength < str.Length) { yield return str.Substring(index, maxLength); index += maxLength; } yield return str.Substring(index); } 

易于理解的版本:

 string x = "AAABBBCC"; List<string> a = new List<string>(); for (int i = 0; i < x.Length; i += 3) { if((i + 3) < x.Length) a.Add(x.Substring(i, 3)); else a.Add(x.Substring(i)); } 

虽然最好3应该是一个不错的常量。

这不是特别简洁,但我可以使用这样的扩展方法:

 public static IEnumerable<string> SplitByLength(this string s, int length) { for (int i = 0; i < s.Length; i += length) { if (i + length <= s.Length) { yield return s.Substring(i, length); } else { yield return s.Substring(i); } } } 

请注意,我返回一个IEnumerable<string> ,而不是一个数组。 如果要将结果转换为数组,请使用ToArray

 string[] arr = x.SplitByLength(3).ToArray(); 

这是我会做的:

 public static IEnumerable<string> EnumerateByLength(this string text, int length) { int index = 0; while (index < text.Length) { int charCount = Math.Min(length, text.Length - index); yield return text.Substring(index, charCount); index += length; } } 

这个方法会提供延迟执行(这对于像string这样的不可变类来说并不重要,但是值得注意)。

那么如果你想要一个方法来为你填充一个数组,你可以有:

 public static string[] SplitByLength(this string text, int length) { return text.EnumerateByLength(length).ToArray(); } 

我之所以使用名称EnumerateByLength而不是SplitByLength作为“core”方法,是因为string.Split返回一个string[] ,所以在我看来,名称以Split开头的方法返回数组的优先顺序。

虽然这只是我。

我的解决scheme

 public static string[] SplitToChunks(this string source, int maxLength) { return source .Where((x, i) => i % maxLength == 0) .Select( (x, i) => new string(source .Skip(i * maxLength) .Take(maxLength) .ToArray())) .ToArray(); } 

我实际上宁愿使用List<string>而不是string[]

在.NET 4.0上使用MoreLinq Batch

 public static IEnumerable<string> SplitByLength(this string str, int length) { return str.Batch(length, String.Concat); } 

在3.5 Concat需要一个数组,所以我们可以使用ConcatToArray或者new String

 public static IEnumerable<string> SplitByLength(this string str, int length) { return str.Batch(length, chars => new String(chars.ToArray())); } 

将string看作字符集合可能有点不直观,因此可能会提供string操作。

又一个轻微的变体(经典而简单实用):

 class Program { static void Main(string[] args) { string msg = "AAABBBCC"; string[] test = msg.SplitByLength(3); } } public static class SplitStringByLength { public static string[] SplitByLength(this string inputString, int segmentSize) { List<string> segments = new List<string>(); int wholeSegmentCount = inputString.Length / segmentSize; int i; for (i = 0; i < wholeSegmentCount; i++) { segments.Add(inputString.Substring(i * segmentSize, segmentSize)); } if (inputString.Length % segmentSize != 0) { segments.Add(inputString.Substring(i * segmentSize, inputString.Length - i * segmentSize)); } return segments.ToArray(); } } 

UPD:使用一些Linq使其实际上简洁

 static IEnumerable EnumerateByLength(string str, int len) { Match m = (new Regex(string.Format("^(.{{1,{0}}})*$", len))).Match(str); if (m.Groups.Count <= 1) return Empty; return (from Capture c in m.Groups[1].Captures select c.Value); } 

初始版本:

 static string[] Empty = new string [] {}; static string[] SplitByLength(string str, int len) { Regex r = new Regex(string.Format("^(.{{1,{0}}})*$",len)); Match m = r.Match(str); if(m.Groups.Count <= 1) return Empty; string [] result = new string[m.Groups[1].Captures.Count]; int ix = 0; foreach(Capture c in m.Groups[1].Captures) { result[ix++] = c.Value; } return result; } 
  private string[] SplitByLength(string s, int d) { List<string> stringList = new List<string>(); if (s.Length <= d) stringList.Add(s); else { int x = 0; for (; (x + d) < s.Length; x += d) { stringList.Add(s.Substring(x, d)); } stringList.Add(s.Substring(x)); } return stringList.ToArray(); } 
  private void button2_Click(object sender, EventArgs e) { string s = "AAABBBCCC"; string[] a = SplitByLenght(s,3); } private string[] SplitByLenght(string s, int split) { //Like using List because I can just add to it List<string> list = new List<string>(); // Integer Division int TimesThroughTheLoop = s.Length/split; for (int i = 0; i < TimesThroughTheLoop; i++) { list.Add(s.Substring(i * split, split)); } // Pickup the end of the string if (TimesThroughTheLoop * split != s.Length) { list.Add(s.Substring(TimesThroughTheLoop * split)); } return list.ToArray(); } 

我有奇怪的场景,我已经分割了一个string,然后重新安排段(即颠倒),然后我连接它们,然后我需要扭转分割。 以下是@SLaks接受的答案的更新 :

  /// <summary> /// Split the given string into equally-sized segments (possibly with a 'remainder' if uneven division). Optionally return the 'remainder' first. /// </summary> /// <param name="str">source string</param> /// <param name="maxLength">size of each segment (except the remainder, which will be less)</param> /// <param name="remainderFirst">if dividing <paramref name="str"/> into segments would result in a chunk smaller than <paramref name="maxLength"/> left at the end, instead take it from the beginning</param> /// <returns>list of segments within <paramref name="str"/></returns> /// <remarks>Original method at https://stackoverflow.com/questions/3008718/split-string-into-smaller-strings-by-length-variable </remarks> private static IEnumerable<string> ToSegments(string str, int maxLength, bool remainderFirst = false) { // note: `maxLength == 0` would not only not make sense, but would result in an infinite loop if(maxLength < 1) throw new ArgumentOutOfRangeException("maxLength", maxLength, "Should be greater than 0"); // correct for the infinite loop caused by a nonsensical request of `remainderFirst == true` and no remainder (`maxLength==1` or even division) if( remainderFirst && str.Length % maxLength == 0 ) remainderFirst = false; var index = 0; // note that we want to stop BEFORE we reach the end // because if it's exact we'll end up with an // empty segment while (index + maxLength < str.Length) { // do we want the 'final chunk' first or at the end? if( remainderFirst && index == 0 ) { // figure out remainder size var remainder = str.Length % maxLength; yield return str.Substring(index, remainder); index += remainder; } // normal stepthrough else { yield return str.Substring(index, maxLength); index += maxLength; } } yield return str.Substring(index); }//--- fn ToSegments 

(如果maxLength==1我也更正了原始版本中的一个错误,导致产生空的段)