2010-12-21 141 views

回答

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; 
} 

(這有可能是你可能獲得更好的性能 - 在兩個LINQ和非LINQ版本 - 如果轉換charsHashSet<char>,或者甚至可能是一個簡單的char[]陣列,你需要進行基準測試才能發現,儘管除非chars變得相當大,否則任何差異都可能忽略不計。)

+1

不錯的工作,但是他們正確的頭腦在圖書館或API程序中發現任何可以接受的東西?看起來像一個MS失敗。 – GTAE86 2014-03-28 18:11:13

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)); 
+3

不完全:'find_first_not_of'返回位置,而不是字符。 – Vlad 2010-12-21 10:58:55

+0

@Vlad,你是對的,回答相應更新。謝謝:) – 2010-12-21 11:06:22

+3

我認爲,LINQ過分複雜的東西。而這個解決方案是非常無效的。我們與迭代器一起創建了很多匿名類型的臨時對象。對於循環來說簡單的書寫方法會更好。 – 2010-12-21 11:15:29

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;