I\'d like to break apart a String by a certain length variable.
It needs to bounds check so as not explode when the last section of string is not as long as or longer th
public List<string> SplitArray(string item, int size)
{
if (item.Length <= size) return new List<string> { item };
var temp = new List<string> { item.Substring(0,size) };
temp.AddRange(SplitArray(item.Substring(size), size));
return temp;
}
Thoug, it does not returns a IEnumerable but a List
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();
}
Yet another slight variant (classic but simple and pragmatic):
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();
}
}
Here's what I'd do:
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;
}
}
This method would provide deferred execution (which doesn't really matter on an immutable class like string
, but it's worth noting).
Then if you wanted a method to populate an array for you, you could have:
public static string[] SplitByLength(this string text, int length) {
return text.EnumerateByLength(length).ToArray();
}
The reason I would go with the name EnumerateByLength
rather then SplitByLength
for the "core" method is that string.Split
returns a string[]
, so in my mind there's precedence for methods whose names start with Split
to return arrays.
That's just me, though.
UPD: Using some Linq to make it actually succinct
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);
}
Initial version:
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;
}
You need to use a loop:
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));
}
}
Alternative:
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;
}
}
2nd alternative: (For those who can't stand 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);
}