C# 使用分隔符拆分字符串,但将结果中的分隔符保留在C中#

C# 使用分隔符拆分字符串,但将结果中的分隔符保留在C中#,c#,string,split,C#,String,Split,我希望使用分隔符拆分字符串,但将分隔符保留在结果中 在C#中如何执行此操作?result=originalString.Split(分隔符); for(int i=0;i

我希望使用分隔符拆分字符串,但将分隔符保留在结果中

在C#中如何执行此操作?

result=originalString.Split(分隔符);
for(int i=0;i
编辑-这是一个糟糕的答案-我误读了他的问题,没有看到他被多个字符分开。)


(编辑-正确的LINQ版本比较麻烦,因为分隔符不应该连接到拆分数组中的最后一个字符串上。)

最近我写了一个扩展方法来解决这个问题:

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;
            }
        }
    }
公共静态类StringExtensions
{
公共静态IEnumerable SplitAndKeep(此字符串s,字符串分隔符)
{
string[]obj=s.Split(新字符串[]{separator},StringSplitOptions.None);
for(int i=0;i
如果拆分字符为
,我会尝试:

using System.Text.RegularExpressions;
...    
string[] parts = Regex.Split(originalString, @"(?<=[.,;])")
使用System.Text.regular表达式;
...    
string[]parts=Regex.Split(originalString,@)(?
使用System.Collections.Generic;
使用System.Text.RegularExpressions;
命名空间控制台应用程序9
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串输入=@“This;is:a.test”;
字符sep0=';',sep1=':',sep2=';
string pattern=string.Format(“[{0}{1}{2}]|[^{0}{1}{2}]+”,sep0,sep1,sep2);
正则表达式正则表达式=新正则表达式(模式);
MatchCollection matches=regex.matches(输入);
列出零件=新列表();
foreach(匹配中的匹配)
{
parts.Add(match.ToString());
}
}
}
}

逐个字符地遍历字符串(这也是正则表达式的作用)。 当您找到一个拆分器时,然后派生一个子字符串

伪码

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;
   }
}
int保持,计数器;
后分裂列表;
弦分裂
用于(保持=0,计数器=0;计数器
这有点像C#,但不是真的。显然,选择合适的函数名。 此外,我认为其中可能有一个off-by-1错误


但这会满足你的要求。

这似乎可行,但没有经过太多测试

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();
}
公共静态字符串[]拆分和keepseparators(字符串值、字符[]分隔符、StringSplitOptions拆分选项)
{
List splitValues=新列表();
int itemStart=0;
for(int pos=0;pos
根据BFree的答案,我也有同样的目标,但我想使用类似于原始拆分方法的字符数组进行拆分,并且每个字符串也有多个拆分:

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);
    }
}
公共静态IEnumerable SplitAndKeep(此字符串为s,char[]delims)
{
int start=0,索引;
而((索引=s.IndexOfAny(delims,start))!=-1)
{
如果(索引开始>0)
收益率返回s.子字符串(开始,索引-开始);
收益率s.子串(指数,1);
开始=索引+1;
}
如果(开始
如果您希望分隔符是其“自己的拆分”,您可以使用,例如:

因此,如果您想要拆分一个数学公式,可以使用以下正则表达式

@"([*()\^\/]|(?<!E)[\+\-])" 

@”([*()\^\/]|)(?我想说实现这一点最简单的方法(除了Hans Kesting提出的参数外)是以常规方式拆分字符串,然后迭代数组,并将分隔符添加到除最后一个之外的每个元素。

以防有人也需要此答案


我没有使用
string[]parts=Regex.Split(originalString,@)(?我想这样做一个多行字符串,但需要保留换行符,所以我这样做了

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

此版本不使用LINQ或正则表达式,因此它可能相对高效。我认为它可能比正则表达式更易于使用,因为您不必担心转义特殊分隔符。它返回一个
IList
,这比始终转换为数组更高效。这是一个扩展方法,非常方便。您可以将分隔符作为数组或多个参数传入

/// <summary>
/// Splits the given string into a list of substrings, while outputting the splitting
/// delimiters (each in its own string) as well. It's 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;
}

这个问题有很多答案!我找到了一个被各种字符串分割的答案(原始答案只适合字符,即长度为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;
}
公共静态IEnumerable SplitAndKeep(字符串s,参数字符串[]delims)
{
var rows=new List(){s};
foreach(delims中的字符串delim)//分隔符计数器
{
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();
    }
var variableSplit = variableName.SplitLeft(
    Enumerable.Range('A', 26).Select(i => (char)i).ToArray());
/// <summary>
/// Splits the given string into a list of substrings, while outputting the splitting
/// delimiters (each in its own string) as well. It's 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], "]");
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;
}
 string[] substrings = Regex.Split(input,@"(?<=[-])");
private static string[] SplitKeepDelimiters(string toSplit, char[] delimiters, StringSplitOptions splitOptions = StringSplitOptions.None)
{
    var tokens = new List<string>();
    int idx = 0;
    for (int i = 0; i < toSplit.Length; ++i)
    {
        if (delimiters.Contains(toSplit[i]))
        {
            tokens.Add(toSplit.Substring(idx, i - idx));  // token found
            tokens.Add(toSplit[i].ToString());            // delimiter
            idx = i + 1;                                  // start idx for the next token
        }
    }

    // last token
    tokens.Add(toSplit.Substring(idx));

    if (splitOptions == StringSplitOptions.RemoveEmptyEntries)
    {
        tokens = tokens.Where(token => token.Length > 0).ToList();
    }

    return tokens.ToArray();
}
string toSplit = "AAA,BBB,CCC;DD;,EE,";
char[] delimiters = new char[] {',', ';'};
string[] tokens = SplitKeepDelimiters(toSplit, delimiters, StringSplitOptions.RemoveEmptyEntries);
foreach (var token in tokens)
{
    Console.WriteLine(token);
}
var delimiter = "ab";
var text = "ab33ab9ab"
var parts = Regex.Split(text, $@"({Regex.Escape(delimiter)})")
                 .Where(p => p != string.Empty)
                 .ToList();

// parts = "ab", "33", "ab", "9", "ab"