给你 - 这适用于任何顺序的任何分隔符组合,也允许在字符串中实际上没有找到分隔符的情况。我花了一段时间才想出这个,并且发布后,它看起来比任何其他答案都复杂!
啊,好吧,我还是把它留在这里。
public static string SplitAndReJoin(string str, char[] delimiters,
Func<string[], string[]> mutator)
{
//first thing to know is which of the delimiters are
//actually in the string, and in what order
//Using ToArray() here to get the total count of found delimiters
var delimitersInOrder = (from ci in
(from c in delimiters
from i in FindIndexesOfAll(str, c)
select new { c, i })
orderby ci.i
select ci.c).ToArray();
if (delimitersInOrder.Length == 0)
return str;
//now split and mutate the string
string[] strings = str.Split(delimiters);
strings = mutator(strings);
//now build a format string
//note - this operation is much more complicated if you wish to use
//StringSplitOptions.RemoveEmptyEntries
string formatStr = string.Join("",
delimitersInOrder.Select((c, i) => string.Format("{{{0}}}", i)
+ c));
//deals with the 'perfect' split - i.e. there's always two values
//either side of a delimiter
if (strings.Length > delimitersInOrder.Length)
formatStr += string.Format("{{{0}}}", strings.Length - 1);
return string.Format(formatStr, strings);
}
public static IEnumerable<int> FindIndexesOfAll(string str, char c)
{
int startIndex = 0;
int lastIndex = -1;
while(true)
{
lastIndex = str.IndexOf(c, startIndex);
if (lastIndex != -1)
{
yield return lastIndex;
startIndex = lastIndex + 1;
}
else
yield break;
}
}
这是一个可以用来验证它的测试:
[TestMethod]
public void TestSplitAndReJoin()
{
//note - mutator does nothing
Assert.AreEqual("a,b", SplitAndReJoin("a,b", ",".ToCharArray(), s => s));
//insert a 'z' in front of every sub string.
Assert.AreEqual("zaaa,zbbbb.zccc|zdddd:zeee", SplitAndReJoin("aaa,bbbb.ccc|dddd:eee",
",.|:".ToCharArray(), s => s.Select(ss => "z" + ss).ToArray()));
//re-ordering of delimiters + mutate
Assert.AreEqual("zaaa,zbbbb.zccc|zdddd:zeee", SplitAndReJoin("aaa,bbbb.ccc|dddd:eee",
":|.,".ToCharArray(), s => s.Select(ss => "z" + ss).ToArray()));
//now how about leading or trailing results?
Assert.AreEqual("a,", SplitAndReJoin("a,", ",".ToCharArray(), s => s));
Assert.AreEqual(",b", SplitAndReJoin(",b", ",".ToCharArray(), s => s));
}
请注意,我假设您需要能够对数组的元素做一些事情,在将它们重新组合在一起之前操纵各个字符串 - 否则您可能只会保留原始字符串!
该方法构建动态格式字符串。这里不保证效率:)