C # разделите строку, но сохраните раздельные символы / разделители
Я разделяю строку на три разных символа, но я хочу, чтобы на выходе включались символы, которые я разделял. Есть ли простой способ сделать это?
- В Java для строки x, какова стоимость выполнения s.length ()? O (1) или O (n)?
- Каков тип строковых литералов в C и C ++?
- Возврат строки из функции C
- Как определить, не определена ли строка в сценарии оболочки bash?
- Как конкатенировать строки с заполнением в sqlite
- Как преобразовать целое число цвета в шестнадцатеричную строку в Android?
- Почему преобразование из строковой константы в 'char *' допустимо в C, но недействительно в C ++
- Как проверить, что строка обрабатывается двойным?
Исходя из ответа BFree, у меня была та же цель, но я хотел разбить массив символов, похожий на оригинальный метод Split, и у меня также есть несколько разделов на строку:
public static IEnumerable SplitAndKeep(this string s, char[] delims) { int start = 0, index; while ((index = s.IndexOfAny(delims, start)) != -1) { if(index-start > 0) yield return s.Substring(start, index - start); yield return s.Substring(index, 1); start = index + 1; } if (start < s.Length) { yield return s.Substring(start); } }
На всякий случай, если кто-то захочет этого ответа …
Вместо string[] parts = Regex.Split(originalString, @"(?<=[.,;])")
Вы можете использовать string[] parts = Regex.Split(originalString, @"(?=yourmatch)")
где yourmatch
- это ваш разделитель.
Предположим, что исходная строка была
777- кошка
777 - собака
777 - мышь
777 - крыса
777 - волк
Regex.Split(originalString, @"(?=777)")
вернется
777 - кошка
777 - собака
и так далее
Это, похоже, работает, но его не очень много тестировали.
public static string[] SplitAndKeepSeparators(string value, char[] separators, StringSplitOptions splitOptions) { List splitValues = new List (); int itemStart = 0; for (int pos = 0; pos < value.Length; pos++) { for (int sepIndex = 0; sepIndex < separators.Length; sepIndex++) { if (separators[sepIndex] == value[pos]) { // add the section of string before the separator // (unless its empty and we are discarding empty sections) if (itemStart != pos || splitOptions == StringSplitOptions.None) { splitValues.Add(value.Substring(itemStart, pos - itemStart)); } itemStart = pos + 1; // add the separator splitValues.Add(separators[sepIndex].ToString()); break; } } } // add anything after the final separator // (unless its empty and we are discarding empty sections) if (itemStart != value.Length || splitOptions == StringSplitOptions.None) { splitValues.Add(value.Substring(itemStart, value.Length - itemStart)); } return splitValues.ToArray(); }
result = originalString.Split(separator); for(int i = 0; i < result.Length - 1; i++) result[i] += separator;
( РЕДАКТИРОВАТЬ - это плохой ответ - я неправильно понял его вопрос и не видел, что он раскалывается несколькими персонажами).
(EDIT - правильная версия LINQ неудобна, поскольку разделитель не должен конкатенироваться с последней строкой в массиве split).
Недавно я написал метод расширения:
public static class StringExtensions { public static IEnumerable 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; } } }
Итерации через строковый символ по символу (это то, что все равно регулярное выражение). Когда вы находите сплиттер, а затем отжимайте подстроку.
псевдокод
int hold, counter; List afterSplit; string toSplit for(hold = 0, counter = 0; counter < toSplit.Length; counter++) { if(toSplit[counter] = /*split charaters*/) { afterSplit.Add(toSplit.Substring(hold, counter)); hold = counter; } }
Это вроде C #, но на самом деле. Очевидно, выберите подходящие имена функций. Кроме того, я думаю, что там может быть ошибка «один за другим».
Но это будет делать то, что вы просите.
Много ответов на это! Один я постучал, чтобы разбить по различным строкам (исходный ответ соответствует только символам, т.е. длине 1). Это не было полностью протестировано.
public static IEnumerable SplitAndKeep(string s, params string[] delims) { var rows = new List () { s }; foreach (string delim in delims)//delimiter counter { for (int i = 0; i < rows.Count; i++)//row counter { int index = rows[i].IndexOf(delim); if (index > -1 && rows[i].Length > index + 1) { string leftPart = rows[i].Substring(0, index + delim.Length); string rightPart = rows[i].Substring(index + delim.Length); rows[i] = leftPart; rows.Insert(i + 1, rightPart); } } } return rows; }
Regex.Split выглядит так, как будто он может делать то, что вы хотите, возможно.
using System.Collections.Generic; using System.Text.RegularExpressions; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { string input = @"This;is:a.test"; char sep0 = ';', sep1 = ':', sep2 = '.'; string pattern = string.Format("[{0}{1}{2}]|[^{0}{1}{2}]+", sep0, sep1, sep2); Regex regex = new Regex(pattern); MatchCollection matches = regex.Matches(input); List parts=new List (); foreach (Match match in matches) { parts.Add(match.ToString()); } } } }
Код Java:
public static class String_Ext { public static string[] SplitOnGroups(this string str, string pattern) { var matches = Regex.Matches(str, pattern); var partsList = new List(); for (var i = 0; i < matches.Count; i++) { var groups = matches[i].Groups; for (var j = 0; j < groups.Count; j++) { var group = groups[j]; partsList.Add(group.Value); } } return partsList.ToArray(); } } var parts = "abcde \tfgh\tikj\r\nlmno".SplitOnGroups(@"\s+|\S+"); for (var i = 0; i < parts.Length; i++) Print(i + "|" + Translate(parts[i]) + "|");
Вывод:
0|abcde| 1| \t| 2|fgh| 3|\t| 4|ikj| 5|\r\n| 6|lmno|