'Split a string by the last index of given character and max length

I want to split a string by last occurrence of a space up to index 40, and remove the space, this is easy enough for a small string:

var address = "...Are included in two of the " +
              "substrings. If you want to exclude";

var splitIndex = address.LastIndexOf(' ', 40);

var address1 = address.Substring(0, splitIndex);
var address2 = address.Substring(splitIndex + 1, address.Length - splitIndex - 1);

But what if the string is large, let's say 1000 characters, in which each substring would have 40 characters or less, deppending on the space location, how would I do this in an elegant manner?

For example, in the above snippet, the space is at index 29, so the first string is from index 0 to 28, removing the space, next I would find the last space from index 30 to 69, let's say it's 62, I would save the second string from 30 to 61, and so on.

This is because I have to send in a payload via POST a list of strings that each can't have more than 40 characters.

Suffice to say that I can't cut words in half (unless a word has more than 40 characters), otherwise it would be much easier.



Solution 1:[1]

I ended up following Mathias R. Jessen comment:

Assign the trailing part to a restOfAddress string variable, then repeat the operation until the rest is an empty string

And turned it into an extension method for String class.

I created a routine to keep spliting the remainder string until it's empty or it's smaller than maximum defined length, at which point we don't need to split anymore and just return the remainder. Here is my solution:

public static class StringExtensions
{
    public static IEnumerable<string> SplitByLastIndexOf(
        this string stringToSplit, 
        int splitMaxLength, char delimiter, 
        bool removeDelimiter = true)
    {
        while (!string.IsNullOrEmpty(stringToSplit))
        {
            if (stringToSplit.Length <= splitMaxLength)
            {
                yield return stringToSplit;
                break;
            }
            var splitIndex = stringToSplit.LastIndexOf(delimiter, splitMaxLength);

            var remove = removeDelimiter ? 1 : 0;

            if (splitIndex == -1)
            {
                splitIndex = splitMaxLength;
                remove = 0;
            }
            
            yield return stringToSplit[..splitIndex];
            stringToSplit = stringToSplit[(splitIndex + remove)..];    
        }
    }
}

Usage:

var restOfAddress = "...Are included in two of the substrings. " +
                    "If you want to exclude the characters, you can " +
                    "add the periods... ...Are included in of the substrings. " +
                    "If you want to exclude the period characters, you can " +
                    "add the period... Some more " +
                    "textVeryveryveryveryveryveryveryveryveryverylargestring " +
                    "some words for edge case";

var addresses = address.SplitByLastIndexOf(40, ' ');

foreach (var address in addresses)
{
    Console.WriteLine(address + " -> " + address.Length);
}

Output:

...Are included in two of the -> 29
substrings. If you want to exclude the -> 38
characters, you can add the periods... -> 38
...Are included in of the substrings. If -> 40
you want to exclude the period -> 30
characters, you can add the period... -> 37
Some more -> 9
textVeryveryveryveryveryveryveryveryvery -> 40
verylargestring some words for edge case -> 40

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1