简体   繁体   English

C#等价于C ++ std :: string find_first_not_of和find_last_not_of

[英]C# equivalent of C++ std::string find_first_not_of and find_last_not_of

IndexOf , IndexOfAny and LastIndexOf , LastIndexOfAny dont seem to do these (or maybe they do). IndexOfIndexOfAnyLastIndexOfLastIndexOfAny似乎没有这些(或者他们可能会这样做)。 I'm looking for the equialent of std::string's find_first_not_of and find_last_not_of . 我正在寻找std :: string的find_first_not_offind_last_not_offind_first_not_of find_last_not_of I'm thinking about creating an extension class but I'm not sure if C# already provides this functionality. 我正在考虑创建一个扩展类,但我不确定C#是否已经提供了这个功能。

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

Or, if you prefer some non-LINQ extension methods. 或者,如果您更喜欢一些非LINQ扩展方法。 These should have slightly better performance, especially for FindLastNotOf : 这些应该具有稍​​好的性能,尤其是对于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;
}

(It's possible that you might get better performance -- in both the LINQ and non-LINQ versions -- if you convert chars to a HashSet<char> , or maybe even a plain char[] array. You'd need to benchmark to find out, though any difference is likely to be negligible unless chars gets pretty big.) (你可能会在LINQ和非LINQ版本中获得更好的性能 - 如果你将chars转换为HashSet<char> ,或者甚至是一个普通的char[]数组。你需要进行基准测试发现,虽然任何差异可能是微不足道的,除非chars变得很大。)

If the use of LINQ is acceptable, you can call the First() and Last() methods with the appropriate predicate. 如果可以使用LINQ,则可以使用适当的谓词调用First()Last()方法。

For instance, if you want the first and last characters that aren't vowels: 例如,如果您想要不是元音的第一个和最后一个字符:

string vowels = "aeiouy";
char first = yourString.First(ch => vowels.IndexOf(ch) < 0);
char last = yourString.Last(ch => vowels.IndexOf(ch) < 0);

EDIT: The above will return the characters, not their indexes. 编辑:上面将返回字符,而不是它们的索引。 In order to do that, you can project the indexes using the Select() method, but things will get hairy since we need to return -1 if no character matches: 为了做到这一点,你可以使用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;

Alternatively, here's a less complicated solution based on @abatishchev's answer: 或者,根据@ 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));

Here's a Regex solution. 这是一个正则表达式解决方案。

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM