【发布时间】:2016-04-08 14:27:25
【问题描述】:
我有一个文本字符串,并希望确保它最多包含一次特定字符 (,)。因此,我想保留第一个,但只需删除该字符的所有进一步出现。
我怎样才能使用 C# 以最优雅的方式做到这一点?
【问题讨论】:
我有一个文本字符串,并希望确保它最多包含一次特定字符 (,)。因此,我想保留第一个,但只需删除该字符的所有进一步出现。
我怎样才能使用 C# 以最优雅的方式做到这一点?
【问题讨论】:
这可行,但肯定不是最优雅的:-)
string a = "12,34,56,789";
int pos = 1 + a.IndexOf(',');
return a.Substring(0, pos) + a.Substring(pos).Replace(",", string.Empty);
【讨论】:
a.IndexOf 替换为返回第 N 次出现的子字符串的方法:stackoverflow.com/questions/186653/…
您可以使用计数器变量和StringBuilder 来有效地创建新字符串:
var sb = new StringBuilder(text.Length);
int maxCount = 1;
int currentCount = 0;
char specialChar = ',';
foreach(char c in text)
if(c != specialChar || ++currentCount <= maxCount)
sb.Append(c);
text = sb.ToString();
这种方法不是最短的,但它很有效,您可以指定要保留的字符数。
这是使用 LINQ 的更“优雅”的方式:
int commasFound = 0; int maxCommas = 1;
text = new string(text.Where(c => c != ',' || ++commasFound <= maxCommas).ToArray());
我不喜欢它,因为它需要修改查询中的变量,所以会产生副作用。
【讨论】:
正则表达式很优雅,对吧?
Regex.Replace("Eats, shoots, and leaves.", @"(?<=,.*),", "");
这将替换每个逗号,只要它前面有一个逗号,什么都没有。
(其实可能不太优雅——可能只有一行代码,但也可能是O(n^2)...)
【讨论】:
如果您不处理大字符串并且您非常喜欢 Linq oneliners:
public static string KeepFirstOccurence (this string @string, char @char)
{
var index = @string.IndexOf(@char);
return String.Concat(String.Concat(@string.TakeWhile(x => @string.IndexOf(x) < index + 1)), String.Concat(@string.SkipWhile(x=>@string.IndexOf(x) < index)).Replace(@char.ToString(), ""));
}
【讨论】:
您可以编写一个类似以下的函数,根据您正在搜索的内容的位置(通过String.Split() 方法)将字符串分成两部分,并且它只会从第二部分中删除匹配项(使用String.Replace()) :
public static string RemoveAllButFirst(string s, string stuffToRemove)
{
// Check if the stuff to replace exists and if not, return the original string
var locationOfStuff = s.IndexOf(stuffToRemove);
if (locationOfStuff < 0)
{
return s;
}
// Calculate where to pull the first string from and then replace the rest of the string
var splitLocation = locationOfStuff + stuffToRemove.Length;
return s.Substring(0, splitLocation) + (s.Substring(splitLocation)).Replace(stuffToRemove,"");
}
你可以简单地调用它:
var output = RemoveAllButFirst(input,",");
更漂亮的方法实际上可能涉及构建一个更干净地处理此问题的扩展方法:
public static class StringExtensions
{
public static string RemoveAllButFirst(this string s, string stuffToRemove)
{
// Check if the stuff to replace exists and if not, return the
// original string
var locationOfStuff = s.IndexOf(stuffToRemove);
if (locationOfStuff < 0)
{
return s;
}
// Calculate where to pull the first string from and then replace the rest of the string
var splitLocation = locationOfStuff + stuffToRemove.Length;
return s.Substring(0, splitLocation) + (s.Substring(splitLocation)).Replace(stuffToRemove,"");
}
}
将通过以下方式调用:
var output = input.RemoveAllButFirst(",");
【讨论】:
StringExtensions 需要是静态类,第一个参数需要是this string s
static string KeepFirstOccurance(this string str, char c)
{
int charposition = str.IndexOf(c);
return str.Substring(0, charposition + 1) +
str.Substring(charposition, str.Length - charposition)
.Replace(c, ' ').Trim();
}
【讨论】:
Linq 很短;将字符串拆分为字符,保持不同的集合并连接回字符串。
text = string.Join("", text.Select(c => c).Distinct());
【讨论】: