Я разделяю строку на три разных символа, но я хочу, чтобы на выходе включались символы, которые я разделял. Есть ли простой способ сделать это?
С# разделите строку, но сохраните раздельные символы/разделители
Ответ 1
Если разделительные символы были ,
, .
и ;
, я бы попробовал:
string[] parts = Regex.Split(originalString, @"(?<=[.,;])")
(?<=PATTERN)
- положительный внешний вид для PATTERN
. Он должен совпадать в любом месте, где предшествующий текст соответствует PATTERN
, поэтому после каждого появления любого из символов должно быть соответствие (и разделение).
Ответ 2
С учетом ответа BFree у меня была та же цель, но я хотел разбить массив символов, похожий на оригинальный метод Split, и у меня также есть несколько разделов на строку:
public static IEnumerable<string> 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);
}
}
Ответ 3
На всякий случай кто-то хочет получить этот ответ...
Вместо string[] parts = Regex.Split(originalString, @"(?<=[.,;])")
вы можете использовать string[] parts = Regex.Split(originalString, @"(?=yourmatch)")
, где yourmatch
- это ваш разделитель.
Предположим, что исходная строка была
777- cat
777 - собака
777 - мышь
777 - крыса
777 - волк
Regex.Split(originalString, @"(?=777)")
вернет
777 - cat
777 - собака
и т.д.
Ответ 4
Это, похоже, работает, но его не тестировали много.
public static string[] SplitAndKeepSeparators(string value, char[] separators, StringSplitOptions splitOptions)
{
List<string> splitValues = new List<string>();
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();
}
Ответ 5
result = originalString.Split(separator);
for(int i = 0; i < result.Length - 1; i++)
result[i] += separator;
( РЕДАКТИРОВАТЬ - это плохой ответ - я неправильно понял его вопрос и не видел, чтобы он разбивал несколько символов.)
(EDIT - правильная версия LINQ неудобна, поскольку разделитель не должен конкатенироваться с последней строкой в массиве split.)
Ответ 6
Недавно я написал метод расширения для этого:
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;
}
}
}
Ответ 7
Итерации по символу строки по символу (это то, что все равно регулярное выражение). Когда вы найдете сплиттер, затем отпустите подстроку.
псевдокод
int hold, counter;
List<String> 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;
}
}
Такой тип С#, но не совсем. Очевидно, выберите подходящие имена функций. Кроме того, я думаю, что там может быть ошибка "вне игры".
Но это будет делать то, что вы просите.
Ответ 8
Много ответов на это! Один я постучал, чтобы разбить по различным строкам (исходный ответ удовлетворяет только символам, то есть длине 1). Это не было полностью протестировано.
public static IEnumerable<string> SplitAndKeep(string s, params string[] delims)
{
var rows = new List<string>() { 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;
}
Ответ 9
Regex.Split выглядит так, как будто он может делать то, что вы хотите, возможно.
Ответ 10
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<string> parts=new List<string>();
foreach (Match match in matches)
{
parts.Add(match.ToString());
}
}
}
}
Ответ 11
Код 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<string>();
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|
Ответ 12
См. Использовать Regex.Split(). Я думаю, u/veggerby ответ лучший. Обратите внимание, что он использует синтаксис группы регулярных выражений (например, '(' и ')'), окружающий сопоставленные разделители, чтобы сохранить их в возвращаемом split.