2012-10-07 8 views
15

इसके बजाय प्रत्येक चरित्र के माध्यम से पाशन के में एक चरित्र के सभी अनुक्रमित पाने के लिए अगर यह एक आप तो इतनी तरह एक सूची पर सूचकांक अपने जोड़ने चाहते है:अधिक कारगर तरीका एक स्ट्रिंग

 var foundIndexes = new List<int>(); 
    for (int i = 0; i < myStr.Length; i++) 
    { 
     if (myStr[i] == 'a') 
      foundIndexes.Add(i); 
    } 
+0

एक चरित्र के लिए यह करने के लिए कोई तेज़ तरीका नहीं है; हालांकि, यदि आप लंबे पैटर्न की खोज कर रहे हैं, तो अलग-अलग एल्गोरिदम मौजूद हैं जो आपको [बॉयर-मूर स्ट्रिंग सर्च एल्गोरिदम] जैसे समय में एक से अधिक वर्ण छोड़ने की अनुमति देते हैं (http://en.wikipedia.org/wiki/Boyer% E2% 80% 93Moore_string_search_algorithm)। –

उत्तर

18

आप string.indexof उपयोग कर सकते हैं , उदाहरण के yield को

string s = "abcabcabcabcabc"; 
    var foundIndexes = new List<int>(); 

    long t1 = DateTime.Now.Ticks; 
    for (int i = s.IndexOf('a'); i > -1; i = s.IndexOf('a', i + 1)) 
     { 
     // for loop end when i=-1 ('a' not found) 
       foundIndexes.Add(i); 
     } 
    long t2 = DateTime.Now.Ticks - t1; // read this value to see the run time 
+0

+1 @cdhowie टिप्पणी से सहमत होने पर, यह प्रदर्शन का आखिरी बिट के लिए लड़ने का प्रयास करने का एक और विकल्प है। मुझे यकीन नहीं है कि अगर 'के लिए' हमेशा सीमाओं को हटा देगा जो इंडेक्सऑफ में मौजूद नहीं हैं, तो चरित्र के दुर्लभ अवसरों के साथ लंबी स्ट्रिंग के लिए तेज़ हो सकता है। –

+0

आपकी टिप्पणियां धारणा पर आधारित है। मैंने परीक्षण किया है मेरा समाधान बहुत तेज़ है। इसे विश्वास करने के लिए परीक्षण करें। दो समाधानों के पहले और बाद में टिक मूल्य की तुलना करें। मैंने अपना जवाब यह दिखाने के लिए संपादित किया है कि मैं इसे कैसे देखता हूं –

+0

क्षमा करें, मैंने कुछ और परीक्षण किए हैं। यह वास्तव में निर्भर करता है कि आपका संयोजन क्या है, यह तेज़ हो सकता है और कुछ समय यह धीमा भी हो सकता है। लेकिन वैसे भी, मुझे लगता है कि मेरा कोड क्लीनर है। –

7

कैसे के बारे में

string xx = "The quick brown fox jumps over the lazy dog"; 

char search = 'f'; 

var result = xx.Select((b, i) => b.Equals(search) ? i : -1).Where(i => i != -1); 
+0

शायद ही अधिक कुशल एल्गोरिदमिक रूप से, आप एक ही चीज़ करने के लिए केवल LINQ का उपयोग कर रहे हैं। जब तक कि कुछ LINQ जादू नहीं चलते हैं, तो दो खोजों को जोड़ती है (मैं LINQ अनुकूलन से घनिष्ठ रूप से परिचित नहीं हूं) पर आपने वास्तव में एक दूसरा पाश पेश किया है और प्रदर्शन को और भी खराब बना दिया है। –

+0

@EdS .: कोई LINQ इसमें निष्पादन में देरी नहीं करता है। यह वास्तव में एक लूप है जो काम करेगा। –

+2

सिंगल लूप या नहीं, यह तेज़ नहीं है और यह सिर्फ कोड का एक साधारण टुकड़ा होना चाहिए। –

5

स्ट्रिंग कम है, तो यह एक बार स्ट्रिंग खोज और समय की संख्या चरित्र प्रकट होता है, तो उस आकार की एक सरणी का आवंटन अप गिनती और स्ट्रिंग खोज दूसरी बार के लिए और अधिक कुशल हो सकता है, सरणी में इंडेक्स रिकॉर्डिंग। यह किसी भी सूची पुन: आवंटन छोड़ देगा।

यह क्या आता है कि स्ट्रिंग कितनी देर तक है और चरित्र कितनी बार प्रकट होता है। यदि स्ट्रिंग लंबा है और चरित्र कुछ बार प्रकट होता है, तो इसे एक बार खोजना और List<int> पर इंडिविटीज़ जोड़ना तेज होगा। यदि चरित्र कई बार प्रकट होता है, तो स्ट्रिंग को दो बार खोजना (एक बार गिनने के लिए, और एक बार सरणी भरने के लिए) तेजी से हो सकता है। वास्तव में जहां टिपिंग पॉइंट कई कारकों पर निर्भर करता है जिन्हें आपके प्रश्न से नहीं लिया जा सकता है।

आप एक से अधिक विभिन्न पात्रों के लिए स्ट्रिंग खोज और अलग से उन अक्षरों के लिए अनुक्रमित की एक सूची प्राप्त करने की आवश्यकता है, यह एक बार स्ट्रिंग के माध्यम से खोज और के रूप में \0 से एक Dictionary<char, List<int>> (या एक List<List<int>> चरित्र ऑफसेट का उपयोग कर निर्माण करने के लिए तेजी से हो सकता है बाहरी सरणी में indicies)।

आखिरकार, आपको बाधाओं को खोजने के लिए अपने आवेदन को बेंचमार्क करना चाहिए। अक्सर जो कोड हम सोचते हैं वह धीरे-धीरे प्रदर्शन करेगा, और हम अपने अधिकांश समय I/O या उपयोगकर्ता इनपुट पर अवरुद्ध करते हैं।

+0

+1 के लिए डालने के लिए धन्यवाद, मैं कुछ समान लिख रहा था, लेकिन मेरे पास कोई बेंचमार्क चलाने का समय नहीं है, इसलिए मैंने फैसला नहीं किया। –

+0

हाउ, अगर आपको मेरी पूछताछ पर कोई फर्क नहीं पड़ता है, तो आप ऐप को बेंचमार्क करने के लिए क्या उपयोग करेंगे? मेरे पास प्रीमियम वीएस नहीं है इसलिए मैं विश्लेषण का उपयोग नहीं कर सकता, केवल व्यावसायिक संस्करण का उपयोग कर सकता हूं। –

5

कच्चे पुनरावृत्ति हमेशा बेहतर & सबसे अनुकूलित है।

जब तक यह थोड़ा जटिल कार्य है, तो आप वास्तव में कभी नहीं एक बेहतर अनुकूलित समाधान के लिए प्राप्त करने की आवश्यकता ...

तो मैं के साथ जारी रखने के लिए सुझाव है:

var foundIndexes = new List<int>(); 

for (int i = 0; i < myStr.Length; i++) 

    if (myStr[i] == 'a') foundIndexes.Add(i); 
8

मैं का उपयोग निम्न एक्सटेंशन विधि सभी देखें परिणाम:

public static IEnumerable<int> AllIndexesOf(this string str, string searchstring) 
{ 
    int minIndex = str.IndexOf(searchstring); 
    while (minIndex != -1) 
    { 
     yield return minIndex; 
     minIndex = str.IndexOf(searchstring, minIndex + searchstring.Length); 
    } 
} 

उपयोग:

IEnumerable<int> result = "foobar".AllIndexesOf("o"); // [1,2] 
संबंधित मुद्दे