Programming

문자열을 줄로 나누는 가장 좋은 방법

procodes 2020. 7. 5. 21:30
반응형

문자열을 줄로 나누는 가장 좋은 방법


여러 줄로 된 줄을 어떻게 줄로 나눕니 까?

나도 알아

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

조금 못 생겼고 빈 줄을 잃습니다. 더 나은 해결책이 있습니까?


  • 보기 흉한 경우 불필요한 ToCharArray통화를 제거하십시오 .

  • \n또는 로 나누려면 \r두 가지 옵션이 있습니다.

    • 배열 리터럴을 사용하십시오. 그러나 이것은 Windows 스타일 줄 끝을위한 빈 줄을 제공합니다 \r\n.

      var result = text.Split(new [] { '\r', '\n' });
      
    • Bart가 나타내는 정규식을 사용하십시오.

      var result = Regex.Split(text, "\r\n|\r|\n");
      
  • 빈 줄을 유지하려면 왜 C #에 명시 적으로 버리라고 지시합니까? ( StringSplitOptionsparameter) – StringSplitOptions.None대신 사용하십시오.


using (StringReader sr = new StringReader(text)) {
    string line;
    while ((line = sr.ReadLine()) != null) {
        // do something
    }
}

업데이트 : 대체 / 비동기 솔루션 여기참조 하십시오 .


이것은 훌륭하게 작동하며 Regex보다 빠릅니다.

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

"\r\n"한 줄 바꿈으로 사용되도록 배열에서 첫 번째 를 갖는 것이 중요합니다 . 위의 Regex 솔루션 중 하나와 동일한 결과를 제공합니다.

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

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

Regex가 약 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

Regex.Split을 사용할 수 있습니다.

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

편집 : |\r(이전) Mac 라인 터미네이터를 설명하기 위해 추가되었습니다 .


빈 줄을 유지하려면 StringSplitOptions를 제거하십시오.

var result = input.Split(System.Environment.NewLine.ToCharArray());

나는이 있었다 다른 대답 잭의 기반으로하지만,이 한 대답을 , 훨씬 빠르게되고 는 비동기 적으로 작동하기 때문에 비록 약간 느린 선호 될 수 있습니다.

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


Slightly twisted, but an iterator block to do it:

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

You can then call:

var result = input.Lines().ToArray();

      char[] archDelim = new char[] { '\r', '\n' };
      words = asset.text.Split(archDelim, StringSplitOptions.RemoveEmptyEntries); 

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

It's tricky to handle mixed line endings properly. As we know, the line termination characters can be "Line Feed" (ASCII 10, \n, \x0A, \u000A), "Carriage Return" (ASCII 13, \r, \x0D, \u000D), or some combination of them. Going back to DOS, Windows uses the two-character sequence CR-LF \u000D\u000A, so this combination should only emit a single line. Unix uses a single \u000A, and very old Macs used a single \u000D character. The standard way to treat arbitrary mixtures of these characters within a single text file is as follows:

  • each and every CR or LF character should skip to the next line EXCEPT...
  • ...if a CR is immediately followed by LF (\u000D\u000A) then these two together skip just one line.
  • String.Empty is the only input that returns no lines (any character entails at least one line)
  • The last line must be returned even if it has neither CR nor LF.

The preceding rule describes the behavior of StringReader.ReadLine and related functions, and the function shown below produces identical results. It is an efficient C# line breaking function that dutifully implements these guidelines to correctly handle any arbitrary sequence or combination of CR/LF. The enumerated lines do not contain any CR/LF characters. Empty lines are preserved and returned as String.Empty.

/// <summary>
/// Enumerates the text lines from the string.
///   ⁃ Mixed CR-LF scenarios are handled correctly
///   ⁃ String.Empty is returned for each empty line
///   ⁃ No returned string ever contains CR or LF
/// </summary>
public static IEnumerable<String> Lines(this String s)
{
    int j = 0, c, i;
    char ch;
    if ((c = s.Length) > 0)
        do
        {
            for (i = j; (ch = s[j]) != '\r' && ch != '\n' && ++j < c;)
                ;

            yield return s.Substring(i, j - i);
        }
        while (++j < c && (ch != '\r' || s[j] != '\n' || ++j < c));
}

Note: If you don't mind the overhead of creating a StringReader instance on each call, you can use the following C# 7 code instead. As noted, while the example above may be slightly more efficient, both of these functions produce the exact same results.

public static IEnumerable<String> Lines(this String s)
{
    using (var tr = new StringReader(s))
        while (tr.ReadLine() is String L)
            yield return L;
}

참고URL : https://stackoverflow.com/questions/1508203/best-way-to-split-string-into-lines

반응형