I want to break a long string by character and line length, without breaking words. Within my string I use "|" as my seperator, and every line must never end with a seperator. I need to break on "|", without breaking words.
I tried the following, which looks at the maximum line length, and makes sure everything fits. Now I have to implement the seperation by "|" character without interupting the check for line length.
int partLength = 35;
string sentence = "Silver badges are awarded for longer term goals. Silver badges are uncommon.";
string[] words = sentence.Split(' ');
var parts = new Dictionary<int, string>();
string part = string.Empty;
int partCounter = 0;
foreach (var word in words)
{
if (part.Length + word.Length < partLength)
{
part += string.IsNullOrEmpty(part) ? word : " " + word;
}
else
{
parts.Add(partCounter, part);
part = word;
partCounter++;
}
}
parts.Add(partCounter, part);
foreach (var item in parts)
{
Console.WriteLine(item.Value);
}
I tried the following for breaking by character "|":
string sentence = "The dog had a bone | a ball | and other toys.";
char charToTrim = '|';
string[] words = sentence.Split();
foreach (string word in words)
Console.WriteLine(word.TrimEnd(charToTrim));
This will print all words on new line, which is not correct. So in a long text, I need to look at the maximum line length, as well as the seperator "|". The words must match within the line, but a new line cannot end with "|".
So the following is correct:
Item 1 | Item 2 | Item 3 | Item 4
| Item 5 | Etc
But the following is not correct:
Item 1 | Item 2 | Item 3 | Item 4 |
Item 5 | Etc
You can't split the string using the |
as you would lose the information about where they existing in the original string. Also you won't be able to do this with foreach
as you need to look ahead when calculating the length of the next string. Taking your original code you can do this:
int partLength = 35;
string sentence = "Item 1 | Item 2 | Item 3 | Item 4 | Item 5 | Etc";
string[] words = sentence.Split(' ');
var parts = new Dictionary<int, string>();
string part = string.Empty;
int partCounter = 0;
for(int i = 0; i < words.Count(); i++)
{
var newLength = part.Length + words[i].Length;
if(words[i] == "|" && i + 1 < words.Count())
{
newLength += words[i + 1].Length;
}
if (newLength < partLength)
{
part += string.IsNullOrEmpty(part) ? words[i] : " " + words[i];
}
else
{
parts.Add(partCounter, part);
part = words[i];
partCounter++;
}
}
parts.Add(partCounter, part);
foreach (var item in parts)
{
Console.WriteLine(item.Value);
}
We still split on a space but we use a for
loop to iterate through the strings. Before we check if the current word fits we need to check if it is a |
. If it is then add the next word as well (if one exists). This should produce the output you are looking for.