Я хотел бы разделить строку с разделителями, но сохранить разделители в результате.
Как мне сделать это на С#?
Я хотел бы разделить строку с разделителями, но сохранить разделители в результате.
Как мне сделать это на С#?
Если вы хотите, чтобы разделитель был его "собственным расщеплением", вы можете использовать Regex.Split, например:
string input = "plum-pear";
string pattern = "(-)";
string[] substrings = Regex.Split(input, pattern); // Split on hyphens
foreach (string match in substrings)
{
Console.WriteLine("'{0}'", match);
}
// The method writes the following to the console:
// 'plum'
// '-'
// 'pear'
Эта версия не использует LINQ или Regex и поэтому, вероятно, относительно эффективна. Я думаю, что это может быть проще в использовании, чем в Regex, потому что вам не нужно беспокоиться о том, чтобы избежать специальных разделителей. Он возвращает IList<string>
, который более эффективен, чем конвертирование в массив. Это метод расширения, который удобен. Вы можете передать разделители как массив или как несколько параметров.
/// <summary>
/// Splits the given string into a list of substrings, while outputting the splitting
/// delimiters (each in its own string) as well. It just like String.Split() except
/// the delimiters are preserved. No empty strings are output.</summary>
/// <param name="s">String to parse. Can be null or empty.</param>
/// <param name="delimiters">The delimiting characters. Can be an empty array.</param>
/// <returns></returns>
public static IList<string> SplitAndKeepDelimiters(this string s, params char[] delimiters)
{
var parts = new List<string>();
if (!string.IsNullOrEmpty(s))
{
int iFirst = 0;
do
{
int iLast = s.IndexOfAny(delimiters, iFirst);
if (iLast >= 0)
{
if (iLast > iFirst)
parts.Add(s.Substring(iFirst, iLast - iFirst)); //part before the delimiter
parts.Add(new string(s[iLast], 1));//the delimiter
iFirst = iLast + 1;
continue;
}
//No delimiters were found, but at least one character remains. Add the rest and stop.
parts.Add(s.Substring(iFirst, s.Length - iFirst));
break;
} while (iFirst < s.Length);
}
return parts;
}
Некоторые модульные тесты:
text = "[a link|http://www.google.com]";
result = text.SplitAndKeepDelimiters('[', '|', ']');
Assert.IsTrue(result.Count == 5);
Assert.AreEqual(result[0], "[");
Assert.AreEqual(result[1], "a link");
Assert.AreEqual(result[2], "|");
Assert.AreEqual(result[3], "http://www.google.com");
Assert.AreEqual(result[4], "]");
Я бы сказал, что самый простой способ выполнить это (за исключением аргумента Ханса Кестинга) - это разбить строку на обычный, затем перебрать массив и добавить разделитель к каждому элементу, кроме последнего.
Я хотел сделать многострочную строку, как это, но мне нужно было сохранить разрывы строк, поэтому я сделал это
string x =
@"line 1 {0}
line 2 {1}
";
foreach(var line in string.Format(x, "one", "two")
.Split("\n")
.Select(x => x.Contains('\r') ? x + '\n' : x)
.AsEnumerable()
) {
Console.Write(line);
}
дает
line 1 one
line 2 two
Я столкнулся с той же проблемой, но с несколькими разделителями. Здесь мое решение:
public static string[] SplitLeft(this string @this, char[] delimiters, int count)
{
var splits = new List<string>();
int next = -1;
while (splits.Count + 1 < count && (next = @this.IndexOfAny(delimiters, next + 1)) >= 0)
{
splits.Add(@this.Substring(0, next));
@this = new string(@this.Skip(next).ToArray());
}
splits.Add(@this);
return splits.ToArray();
}
Пример с разделением имен переменных CamelCase:
var variableSplit = variableName.SplitLeft(
Enumerable.Range('A', 26).Select(i => (char)i).ToArray());
Чтобы избежать добавления символа в новую строку, попробуйте следующее:
string[] substrings = Regex.Split(input,@"(?<=[-])");