IndexOf
,IndexOfAny
和LastIndexOf
,LastIndexOfAny
似乎没有这些(或者他们可能会这样做)。我正在寻找std :: string的find_first_not_of
和find_last_not_of
的等价物。我正在考虑创建一个扩展类,但我不确定C#是否已经提供了这个功能。
答案 0 :(得分:11)
string source = "the quick brown fox jumps over the lazy dog";
string chars = "ogd hte";
int? firstNotOf = source.Select((x, i) => new { Val = x, Idx = (int?)i })
.Where(x => chars.IndexOf(x.Val) == -1)
.Select(x => x.Idx)
.FirstOrDefault();
int? lastNotOf = source.Select((x, i) => new { Val = x, Idx = (int?)i })
.Where(x => chars.IndexOf(x.Val) == -1)
.Select(x => x.Idx)
.LastOrDefault();
或者,如果您更喜欢某些非LINQ扩展方法。这些应该有稍微好一点的性能,尤其是FindLastNotOf
:
int? firstNotOf = source.FindFirstNotOf(chars);
int? lastNotof = source.FindLastNotOf(chars);
// ...
public static int? FindFirstNotOf(this string source, string chars)
{
if (source == null) throw new ArgumentNullException("source");
if (chars == null) throw new ArgumentNullException("chars");
if (source.Length == 0) return null;
if (chars.Length == 0) return 0;
for (int i = 0; i < source.Length; i++)
{
if (chars.IndexOf(source[i]) == -1) return i;
}
return null;
}
public static int? FindLastNotOf(this string source, string chars)
{
if (source == null) throw new ArgumentNullException("source");
if (chars == null) throw new ArgumentNullException("chars");
if (source.Length == 0) return null;
if (chars.Length == 0) return source.Length - 1;
for (int i = source.Length - 1; i >= 0; i--)
{
if (chars.IndexOf(source[i]) == -1) return i;
}
return null;
}
(如果您将chars
转换为HashSet<char>
,或者可能可能在LINQ和非LINQ版本中获得更好的性能甚至是一个普通的char[]
数组。你需要通过基准测试才能找到答案,但除非chars
变得非常大,否则任何差异都可以忽略不计。)
答案 1 :(得分:4)
如果可以使用LINQ,您可以使用适当的谓词调用First()和Last()方法。
例如,如果你想要第一个和最后一个不是元音的字符:
string vowels = "aeiouy";
char first = yourString.First(ch => vowels.IndexOf(ch) < 0);
char last = yourString.Last(ch => vowels.IndexOf(ch) < 0);
编辑:以上将返回字符,而不是其索引。为了做到这一点,你可以使用Select()方法来设计索引,但是如果没有字符匹配我们需要返回-1
,事情就会变得毛茸茸:
int firstIndex = (yourString.Select(
(ch, i) => new { Character = ch, Index = i }
).First(obj => vowels.IndexOf(obj.Character) < 0)
?? new { Character = '\0', Index = -1 }).Index;
int lastIndex = (yourString.Select(
(ch, i) => new { Character = ch, Index = i }
).Last(obj => vowels.IndexOf(obj.Character) < 0)
?? new { Character = '\0', Index = -1 }).Index;
或者,根据@ abatishchev的回答,这是一个不太复杂的解决方案:
string vowels = "aeiouy";
int firstIndex = yourString.IndexOf(yourString.First(
ch => vowels.IndexOf(ch) < 0));
int lastIndex = yourString.LastIndexOf(yourString.Last(
ch => vowels.IndexOf(ch) < 0));
答案 2 :(得分:0)
这是一个正则表达式解决方案。
string testString = "oueytestie";
var matchFirstNotOf = Regex.Match(testString, @"[^aeiouy]");
int firstNotOf = matchFirstNotOf.Success ? matchFirstNotOf.Index : -1;
var matchLastNotOf = Regex.Match(testString, @"[^aeiouy]", RegexOptions.RightToLeft);
int lastNotOf = matchLastNotOf.Success ? matchLastNotOf.Index : -1;