Как разбить строку на символ и длину строки, не разбивая слова? - PullRequest
0 голосов
/ 12 ноября 2019

Я хочу разбить длинную строку по символам и длине строки, не разбивая слова. В моей строке я использую "|"как мой разделитель, и каждая строка никогда не должна заканчиваться разделителем. Мне нужно разбить на «|», не разбивая слов.

Я попробовал следующее, которое смотрит на максимальную длину строки и проверяет, все ли подходит. Теперь я должен осуществить разделение с помощью "|"символ без прерывания проверки длины строки.

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);
        }

Я пробовал следующее для разбивки по символу "|":

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));

Это напечатает все слова в новой строке, что не правильно. Поэтому в длинном тексте мне нужно взглянуть на максимальную длину строки, а также на разделитель «|». Слова должны совпадать в пределах строки, но новая строка не может заканчиваться на «|».

Таким образом, верно следующее:

Item 1 |Элемент 2 |Пункт 3 |Элемент 4
|Элемент 5 |Etc

Но следующее неверно:

Item 1 |Элемент 2 |Пункт 3 |Элемент 4 |
Элемент 5 |Etc

Ответы [ 2 ]

1 голос
/ 12 ноября 2019

Изменение вашего примера (и следование вашему первоначальному подходу) Я смог сделать это следующим образом (идея состоит в том, чтобы заглянуть еще на одно слово вперед, если мы встретим разделитель):

int partLength = 15;
string sentence = "Item1 | Item2 | Item3 | Item4 | Item5 | Item6 | Item7 |";
string[] words = sentence.Split(' ');
var parts = new List<string>();
var partBuilder = new StringBuilder(partLength);
int partCounter = 0;

for (int i = 0; i < words.Length; i++)
{
    var word = words[i];
    var nextWord = (i < words.Length - 1) 
        ? words[i + 1]
        : null;
    var lengthToCheck = 
        word == "|" && nextWord != null
            ? word.Length + nextWord.Length
            : word.Length;

    if (partBuilder.Length + lengthToCheck < partLength)
    {
        if (partBuilder.Length > 0)
            partBuilder.Append(" ");
        partBuilder.Append(word);
    }
    else
    {
        parts.Add(partBuilder.ToString());
        partBuilder.Clear();
        partBuilder.Append(word);
        partCounter++;
    }
}
parts.Add(partBuilder.ToString());

foreach (var item in parts)
{
    Console.WriteLine(item);
}

Выводэто:

Item1 | Item2
| Item3 | Item4
| Item5 | Item6
| Item7 |

Я также заменил конкатенацию строк на StringBuilder , что считается наилучшей практикой, когда речь идет о конкатенации большого количества строк.

И я до сих пору меня хватит смелости чувствовать, что это еще проще решить, перемещаясь по строковому символу за символом.

1 голос
/ 12 ноября 2019

Вы не можете разделить строку, используя |, так как вы потеряете информацию о том, где они существуют в исходной строке. Также вы не сможете сделать это с foreach, так как вам нужно смотреть в будущее при расчете длины следующей строки. Взяв исходный код, вы можете сделать это:

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);
}

Мы все еще разделяем пробел, но мы используем цикл for для перебора строк. Прежде чем мы проверим, подходит ли текущее слово, нам нужно проверить, является ли оно |. Если это так, то добавьте следующее слово (если оно существует). Это должно дать результат, который вы ищете.

...