Как разбить строку при сохранении окончания строки? - PullRequest
3 голосов
/ 29 января 2009

У меня есть блок текста, и я хочу получить его строки без потери в конце \ r и \ n. Прямо сейчас у меня есть следующее (неоптимальный код):

string[] lines = tbIn.Text.Split('\n')
                     .Select(t => t.Replace("\r", "\r\n")).ToArray();

Так что мне интересно - есть ли лучший способ сделать это?

Принятый ответ

string[] lines =  Regex.Split(tbIn.Text, @"(?<=\r\n)(?!$)");

Ответы [ 6 ]

6 голосов
/ 29 января 2009

Следующее, кажется, делает работу:

string[] lines =  Regex.Split(tbIn.Text, @"(?<=\r\n)(?!$)");

(? <= \ R \ n) использует «положительный вид сзади» для сопоставления после \ r \ n без его использования. </p>

(?! $) Использует отрицательный прогноз для предотвращения сопоставления в конце ввода и, таким образом, избегает последней строки, которая является просто пустой строкой.

0 голосов
/ 29 января 2009

Как всегда, метод продления вкусности:)

public static class StringExtensions
{
    public static IEnumerable<string> SplitAndKeep(this string s, string seperator)
    {
        string[] obj = s.Split(new string[] { seperator }, StringSplitOptions.None);

        for (int i = 0; i < obj.Length; i++)
        {
            string result = i == obj.Length - 1 ? obj[i] : obj[i] + seperator;
            yield return result;
        }
    }
}

использование:

        string text = "One,Two,Three,Four";
        foreach (var s in text.SplitAndKeep(","))
        {
            Console.WriteLine(s);
        }

Выход:

Один

Два

Три

Четыре

0 голосов
/ 29 января 2009

Вы можете достичь этого с помощью регулярного выражения. Вот метод расширения с ним:

    public static string[] SplitAndKeepDelimiter(this string input, string delimiter)
    {
        MatchCollection matches = Regex.Matches(input, @"[^" + delimiter + "]+(" + delimiter + "|$)", RegexOptions.Multiline);
        string[] result = new string[matches.Count];
        for (int i = 0; i < matches.Count ; i++)
        {
            result[i] = matches[i].Value;
        }
        return result;
    }

Я не уверен, что это лучшее решение. Ваш очень компактный и простой.

0 голосов
/ 29 января 2009

Дмитрий, ваше решение на самом деле довольно компактное и прямолинейное. Единственное, что может быть более эффективным, - это сохранить символов разделения строк в сгенерированном массиве, но API просто не допускают этого. В результате каждое решение потребует итерации по массиву и выполнения некоторой модификации (что в C # означает выделение новых строк каждый раз). Я думаю, что лучшее, на что вы можете надеяться, это не создавать заново массив:

string[] lines = tbIn.Text.Split('\n');
for (int i = 0; i < lines.Length; ++i)
{
    lines[i] = lines[i].Replace("\r", "\r\n");
}

... но, как вы можете видеть, это выглядит намного более громоздким! Если производительность имеет значение, это может быть немного лучше. Если значение действительно имеет значение, вам следует вручную проанализировать строку, используя IndexOf (), чтобы найти единицу за раз, а затем создать массив самостоятельно. Хотя это значительно больше кода и, вероятно, не обязательно.

Одним из побочных эффектов как вашего решения, так и этого является то, что вы не получите завершающий "\ r \ n" в последней строке, если не было ' Один из них уже есть в TextBox. Это то, что вы ожидаете? А как насчет пустых строк ... вы ожидаете, что они появятся в «строках»?

0 голосов
/ 29 января 2009

Что-то вроде использования этого регулярного выражения: [^ \ П \ г] * \ г \ п

Затем используйте Regex.Matches (). Проблема в том, что вам нужно Group (1) из каждого совпадения и создать список строк из этого. В Python вы просто используете функцию map (). Не уверен, что лучший способ сделать это в .NET, вы берете его оттуда; -)

0 голосов
/ 29 января 2009

Если вы просто собираетесь заменить символ новой строки (\n), сделайте что-то вроде этого:

string[] lines = tbIn.Text.Split('\n')
                     .Select(t => t + "\r\n").ToArray();

Редактировать: Regex.Replace позволяет разбивать строку.

string[] lines = Regex.Split(tbIn.Text, "\r\n")
             .Select(t => t + "\r\n").ToArray();
...