由于似乎没有人给出令人满意的答案,我想出了一个。这是一个基于字符串的解决方案(.Net 4):
public static string RemoveRepeatedSpaces(this string s)
{
return s[0] + string.Join("",
s.Zip(
s.Skip(1),
(x, y) => x == y && y == ' ' ? (char?)null : y));
}
但是,这只是从序列中删除重复元素的一般情况,所以这里是通用版本:
public static IEnumerable<T> RemoveRepeatedElements<T>(
this IEnumerable<T> s, T dup)
{
return s.Take(1).Concat(
s.Zip(
s.Skip(1),
(x, y) => x.Equals(y) && y.Equals(dup) ? (object)null : y)
.OfType<T>());
}
当然,这实际上只是一个更具体的函数版本,可以从输入流中删除所有连续重复项:
public static IEnumerable<T> RemoveRepeatedElements<T>(this IEnumerable<T> s)
{
return s.Take(1).Concat(
s.Zip(
s.Skip(1),
(x, y) => x.Equals(y) ? (object)null : y)
.OfType<T>());
}
显然你可以根据第二个函数来实现第一个函数:
public static string RemoveRepeatedSpaces(this string s)
{
return string.Join("", s.RemoveRepeatedElements(' '));
}
顺便说一句,我将我的最后一个函数与正则表达式版本 (Regex.Replace(s, " +", " ")) 进行了基准测试,它们之间的时间相差不到几纳秒,因此与额外的正则表达式开销相比,额外的 LINQ 开销可以忽略不计。当我将它概括为删除所有连续的重复字符时,等效的正则表达式 (Regex.Replace(s, "(.)\\1+", "$1")) 比我的 LINQ 版本 (string.Join("", s.RemoveRepeatedElements())) 慢 3.5 倍。
我也尝试了“理想”的程序解决方案:
public static string RemoveRepeatedSpaces(string s)
{
StringBuilder sb = new StringBuilder(s.Length);
char lastChar = '\0';
foreach (char c in s)
if (c != ' ' || lastChar != ' ')
sb.Append(lastChar = c);
return sb.ToString();
}
这比正则表达式快 5 倍以上!