Лучший способ разделить строку на строки
Как разбить многострочную строку на строки?
Я знаю этот путь
var result = input.Split("nr".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
выглядит немного некрасиво и теряет пустых строк. Есть ли лучшее решение?
9 ответов:
если это выглядит некрасиво, просто удалить ненужные
ToCharArray
звонок.если вы хотите разделить либо
\n
или\r
, у вас есть два варианта:
используйте литерал массива – но это даст вам пустые строки для окончаний строк в стиле Windows
\r\n
:var result = text.Split(new [] { '\r', '\n' });
используйте регулярное выражение, как указано Барт:
var result = Regex.Split(text, "\r\n|\r|\n");
если вы хотите сохранить пустые строки, почему вы явно говорите C# выбросить их? (
using (StringReader sr = new StringReader(text)) { string line; while ((line = sr.ReadLine()) != null) { // do something } }
Вы можете использовать регулярное выражение.Сплит:
string[] tokens = Regex.Split(input, @"\r?\n|\r");
правка: добавил
|\r
для учета (более старых) Терминаторов строк Mac.
Обновление: См.здесь для альтернативного / асинхронного решения.
это прекрасно работает и быстрее, чем регулярное выражение:
input.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.None)
важно
"\r\n"
сначала в массиве, так что он принимается за один разрыв строки. Вышеизложенное дает те же результаты, что и любое из этих регулярных выражений: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
Если вы хотите сохранить пустые строки, просто удалите 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
слегка скрученный, но блок итератора для этого:
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();
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(); }