tags:

views:

854

answers:

6

Hello.

Maybe a basic question but lets say I have a string that is 2000 characters long, I need to split this string into max 512 character chunks each.

Is there a nice way, eg. a loop for doing this?

Thank you :-)

+4  A: 

Something like this:

private IList<string> SplitIntoChunks(string text, int chunkSize)
{
    List<string> chunks = new List<string>();
    int offset = 0;
    while (offset < text.Length)
    {
        int size = Math.Min(chunkSize, text.Length - offset);
        chunks.Add(text.Substring(offset, size));
        offset += size;
    }
    return chunks;
}

Or just to iterate over:

private IEnumerable<string> SplitIntoChunks(string text, int chunkSize)
{
    int offset = 0;
    while (offset < text.Length)
    {
        int size = Math.Min(chunkSize, text.Length - offset);
        yield return text.Substring(offset, size);
        offset += size;
    }
}
Jon Skeet
dammit Jon you beat me to it, and I used your implementation too...
Stan R.
I learned a lot from this one. Accept and +1. Very nice!
meep
+2  A: 
static IEnumerable<string> Split(string str, int chunkSize)    
{   
    int len = str.Length;
    return Enumerable.Range(0, len / chunkSize).Select(i => str.Substring(i * chunkSize, chunkSize));    
}

source: http://stackoverflow.com/questions/1450774/c-split-a-string-into-equal-chunks-each-of-size-4

Chris Ballance
+1 for creativity, -1 for performance and readability
Foxfire
Fails to provide the final chunk in this case.
Jon Skeet
A: 

Something like?

Calculate eachLength = StringLength / WantedCharLength
Then for (int i = 0; i < StringLength; i += eachLength)
SubString (i, eachLength);
Foxfire
A: 

I will dare to provide a more LINQified version of Jon's solution, based on the fact that the string type implements IEnumerable<char>:

private IList<string> SplitIntoChunks(string text, int chunkSize)
{
    var chunks = new List<string>();
    int offset = 0;
    while(offset < text.Length) {
        chunks.Add(new string(text.Skip(offset).Take(chunkSize).ToArray()));
        offset += chunkSize;
    }
    return chunks;
}
Konamiman
I did consider that - particularly as MoreLINQ provides a nice Partition method for this sort of thing. However, the efficiency of this would be absolutely horrible :(
Jon Skeet
It is good to know that, since I tend to use LINQ for everything...
Konamiman
btw String, does not have an extension method for "Skip" you would have to do ToCharArray first.
Stan R.
and I know it implements *IEnumerable<char>* which makes it that much more baffling...
Stan R.
`"foo".Skip(2)` works fine for me...
Joel Mueller
@Stan: the C# VS team hard-coded the string dropdown helpers: it is an exceptional case where you do not see the Framework-provided extensions methods. They found that clearer. The VB team decided contrary: here you do see the `IEnumerable<char>` extension methods in the dropdown helper.
Abel
ahh guys that explains it, thanks...and i was baffled by this for a few minutes hahaa
Stan R.
+1  A: 

using Jon's implementation and the yield keyword.

IEnumerable<string> Chunks(string strText, int chunkSize)
{
    for (int offset = 0; offset < text.Length; offset += size)
    {
        int size = Math.Min(chunkSize, text.Length - offset);
        yield return text.Substring(offset, size);
    }

    yield break;
}
Stan R.
Interesting use of for vs my while... I'm trying to decide which is easier to read. You don't need the yield break at the end, btw.
Jon Skeet
+1  A: 

Though this question meanwhile has an accepted answer, here's a short version with the help of regular expressions. Purists may not like it (understandably) but when you need a quick solution and you are handy with regexes, this can be it. Performance is rather good, surprisingly:

string [] split = Regex.Split(yourString, @"(?<=\G.{512})");

What it does? Negative look-backward and remembering the last position with \G. It will also catch the last bit, even if it isn't dividable by 512.

Abel