166

複数行の文字列をどのように行に分割しますか?

私はこのように知っています

var result = input.Split("\n\r".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

少し見栄えが悪く、空の行が失われます。より良い解決策はありますか?

4

11 に答える 11

207
  • 見た目が悪い場合は、不要なToCharArray呼び出しを削除してください。

  • \nまたはで分割する場合は\r、次の 2 つのオプションがあります。

    • 配列リテラルを使用します。ただし、これにより、Windows スタイルの行末に空の行が表示されます\r\n

      var result = text.Split(new [] { '\r', '\n' });
      
    • Bart が示すように、正規表現を使用します。

      var result = Regex.Split(text, "\r\n|\r|\n");
      
  • 空行を保持したいのに、C# に空行を破棄するように明示的に指示するのはなぜですか? (StringSplitOptionsパラメータ) –StringSplitOptions.None代わりに使用します。

于 2009-10-02T07:53:21.803 に答える
148
using (StringReader sr = new StringReader(text)) {
    string line;
    while ((line = sr.ReadLine()) != null) {
        // do something
    }
}
于 2011-07-29T13:17:55.660 に答える
70

更新:代替/非同期ソリューションについては、こちらを参照してください。


これはうまく機能し、正規表現よりも高速です。

input.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.None)

"\r\n"1 つの改行と見なされるように、配列の最初にあることが重要です。上記は、これらの正規表現ソリューションのいずれかと同じ結果をもたらします。

Regex.Split(input, "\r\n|\r|\n")

Regex.Split(input, "\r?\n|\r")

ただし、正規表現は約 10 倍遅いことが判明しています。これが私のテストです:

Action<Action> measure = (Action func) => {
    var start = DateTime.Now;
    for (int i = 0; i < 100000; i++) {
        func();
    }
    var duration = DateTime.Now - start;
    Console.WriteLine(duration);
};

var input = "";
for (int i = 0; i < 100; i++)
{
    input += "1 \r2\r\n3\n4\n\r5 \r\n\r\n 6\r7\r 8\r\n";
}

measure(() =>
    input.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.None)
);

measure(() =>
    Regex.Split(input, "\r\n|\r|\n")
);

measure(() =>
    Regex.Split(input, "\r?\n|\r")
);

出力:

00:00:03.8527616

00:00:31.8017726

00:00:32.5557128

拡張メソッドは次のとおりです。

public static class StringExtensionMethods
{
    public static IEnumerable<string> GetLines(this string str, bool removeEmptyLines = false)
    {
        return str.Split(new[] { "\r\n", "\r", "\n" },
            removeEmptyLines ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None);
    }
}

使用法:

input.GetLines()      // keeps empty lines

input.GetLines(true)  // removes empty lines
于 2014-08-08T04:21:09.820 に答える
36

Regex.Split を使用できます。

string[] tokens = Regex.Split(input, @"\r?\n|\r");

編集:(|\r古い)Macラインターミネータを考慮して追加。

于 2009-10-02T07:53:39.180 に答える
11

空行を保持したい場合は、StringSplitOptions を削除してください。

var result = input.Split(System.Environment.NewLine.ToCharArray());
于 2009-10-02T07:57:23.727 に答える
5

私はこの他の答えを持っていましたが、ジャックの答えに基づいたこれは、非同期で動作するため、少し遅いですが、かなり速い方が好ましいかもしれません。

public static class StringExtensionMethods
{
    public static IEnumerable<string> GetLines(this string str, bool removeEmptyLines = false)
    {
        using (var sr = new StringReader(str))
        {
            string line;
            while ((line = sr.ReadLine()) != null)
            {
                if (removeEmptyLines && String.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                yield return line;
            }
        }
    }
}

使用法:

input.GetLines()      // keeps empty lines

input.GetLines(true)  // removes empty lines

テスト:

Action<Action> measure = (Action func) =>
{
    var start = DateTime.Now;
    for (int i = 0; i < 100000; i++)
    {
        func();
    }
    var duration = DateTime.Now - start;
    Console.WriteLine(duration);
};

var input = "";
for (int i = 0; i < 100; i++)
{
    input += "1 \r2\r\n3\n4\n\r5 \r\n\r\n 6\r7\r 8\r\n";
}

measure(() =>
    input.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)
);

measure(() =>
    input.GetLines()
);

measure(() =>
    input.GetLines().ToList()
);

出力:

00:00:03.9603894

00:00:00.0029996

00:00:04.8221971

于 2016-12-16T03:31:23.330 に答える
2

少しねじれていますが、それを行うイテレータ ブロック:

public static IEnumerable<string> Lines(this string Text)
{
    int cIndex = 0;
    int nIndex;
    while ((nIndex = Text.IndexOf(Environment.NewLine, cIndex + 1)) != -1)
    {
        int sIndex = (cIndex == 0 ? 0 : cIndex + 1);
        yield return Text.Substring(sIndex, nIndex - sIndex);
        cIndex = nIndex;
    }
    yield return Text.Substring(cIndex + 1);
}

その後、次のように呼び出すことができます。

var result = input.Lines().ToArray();
于 2009-10-02T08:08:27.297 に答える
1
    private string[] GetLines(string text)
    {

        List<string> lines = new List<string>();
        using (MemoryStream ms = new MemoryStream())
        {
            StreamWriter sw = new StreamWriter(ms);
            sw.Write(text);
            sw.Flush();

            ms.Position = 0;

            string line;

            using (StreamReader sr = new StreamReader(ms))
            {
                while ((line = sr.ReadLine()) != null)
                {
                    lines.Add(line);
                }
            }
            sw.Close();
        }



        return lines.ToArray();
    }
于 2015-08-06T00:55:53.077 に答える