2010-12-21 12 views
8

IndexOf, IndexOfAny और LastIndexOf, LastIndexOfAny find_last_not_of न इन करने के लिए (या शायद वे करते हैं) लगते हैं। मैं std :: string's find_first_not_of और find_last_not_of के बराबर की तलाश में हूं। मैं एक विस्तार वर्ग बनाने के बारे में सोच रहा हूं लेकिन मुझे यकीन नहीं है कि सी # पहले से ही इस कार्यक्षमता प्रदान करता है।सी बराबर # और

उत्तर

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 संस्करणों में - यदि आप एक HashSet<char> करने के लिए chars कनवर्ट करते हैं, या शायद एक सादा char[] सरणी। आपको पता लगाने के लिए बेंचमार्क की आवश्यकता होगी, हालांकि chars बहुत बड़ा हो जाता है, हालांकि कोई अंतर नगण्य होने की संभावना है।)

+1

अच्छा काम है, लेकिन उनके सही दिमाग में कौन सा पुस्तकालय या एपीआई दिनचर्या पर स्वीकार्य है? ऐसा लगता है कि एक एमएस असफल हो जाता है। – GTAE86

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

+0

@Vlad, आप सही हैं, जवाब के अनुसार अद्यतन किया गया है। धन्यवाद :) –

+3

मुझे लगता है कि LINQ चीजों को कम करता है। और यह समाधान बहुत अप्रभावी है। हम iterators के साथ अनाम प्रकार के अस्थायी वस्तुओं की बहुत सारी चीजें बना रहे हैं। लूप के लिए सरल लेखन विधि बेहतर होगी। –

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; 
संबंधित मुद्दे