none
Anzahl der Vorkommen von String1 in String2 überprüfen, leerzeichen ignorieren RRS feed

  • Frage

  • Ich muss in einem string die anzahl der Vorkommen von string2 zählen oder ersetzen. Ich dachte da an Regex.Matches bzw. Regex.Replace, aber dann fiel mir ein das ich ja auchoch die Leerzeichen ignorieren muss, also:

    string input = "abc def gab cde fga bcd efg"; string pattern = "abc"; int x = SucheVorkommenVon(input, pattern); //x sollte jetzt 3 sein
    string s = Ersetze(input, pattern, "123");
    //s sollte jetzt "123 def g123de fg123d efg" sein



    Gibt es da eine möglichkeit, oder müsste ich soas selbst schreiben?

    Koopakiller - http://koopakiller.ko.ohost.de/


    Mittwoch, 22. Februar 2012 18:21
    Moderator

Antworten

  • Als regulären Ausdruck kannst du @"a\s*b\s*c" wählen:

                string input = "abc def gab cde fga bcd efg";
                string pattern = @"a\s*b\s*c";
    
                Console.WriteLine(Regex.Matches(input, pattern).Count);


    MVP Data Platform Development My blog

    Mittwoch, 22. Februar 2012 18:29
  • Mein Problem liegt leider darin das input ein x-beliebiger Text sein kann.

    Den input kannst du doch einfach als erstes Argument an die Matches-Methode übergeben, da sehe ich nicht das Problem.

    Wenn du als pattern die Zeichenkette "abc" erhälst, aber dabei Leerzeichen zwischen (und auch vor?) den Zeichen erlauben willst, dann muss man das Pattern erst erstellen, etwa per

                string input = "abc def gab cde fga bcd efg";
                string inputPattern = "abc";
    
                StringBuilder sb = new StringBuilder();
                sb.Append(@"\s*");
                foreach (char c in inputPattern)
                {
                    sb.Append(c);
                    sb.Append(@"\s*");
                }
    
                string pattern = sb.ToString();
                
    
                Console.WriteLine(Regex.Matches(input, pattern).Count);
    Ansonsten musst du detailierter erklären, wie die Zeichenketten aussehen können, die du erhälst, und was genau geprüft werden soll.


    MVP Data Platform Development My blog

    Donnerstag, 23. Februar 2012 11:03
  • Hallo K.,

    das sollte eigentlich mit der Replace-Methode von String oder StringBuilder machbar sein:

                const string input = "abc def gab cde fga bcd efg";
                const string searchPattern = "abc";
                const string replacePattern = "123";
    
                StringBuilder replaced = new StringBuilder(input);
                replaced.Replace(" ", String.Empty);   // Leerzeichen entfernen
                replaced.Replace(searchPattern, replacePattern);
                
                string resultStr = replaced.ToString();
    

    Falls du die Leerzeichen wieder an den alten Positionen eingefügt haben willst, musst du nur die Positionen vorher merken und danach wieder einfügen:

                const string input = "abc def gab cde fga bcd efg";
                const string searchPattern = "abc";
                const string replacePattern = "123";
    
                string[] words = input.Split(' ');   // Positionen merken
    
                StringBuilder replaced = new StringBuilder(input);
                replaced.Replace(" ", String.Empty);
                replaced.Replace(searchPattern, replacePattern);
                
    
    // gemerkte Leerzeichen wieder einfügen
                int startPos = 0;
                foreach (string s in words) {
                    replaced.Insert(startPos + s.Length, ' ');
                    startPos += s.Length + 1;
                }
    
                string resultStr = replaced.ToString();
    

    Dies funktioniert jedoch nur korrekt, wenn der zu ersetzende String gleich lang wie der ersetzte ist.

    Ausserdem stimmt das Ergebnis zwar mit deiner Anforderungsbeschreibung, jedoch nicht mit deinem gewünschten Ergebnis überein, da du in deinem Beispielergebnis auch Leerzeichen die innerhalb des gefundenen Patterns sind, entfernt hast.

    Donnerstag, 23. Februar 2012 14:38
  • Danke für die Hilfe :)Ich habe mal 2 Funktionen geschrieben die genau das macen was ich will:
            private int Matches(string input, string pattern, bool IgnoreCase)
            {
                return Regex.Matches(input.Replace(" ", ""), pattern.Replace(" ", ""), IgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None).Count;
            }
    
            private string Replace(string input, string pattern, string replace, bool IgnoreCase)
            {
                StringBuilder sb = new StringBuilder();
    
                foreach (char c in pattern.Replace(" ", ""))
                {
                    sb.Append(c);
                    sb.Append(@"\s*");
                }
    
                return Regex.Replace(input, sb.ToString().Substring(0, sb.ToString().Length - 3), replace, IgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None);
            }

    Das IgnoreCase bezieht sich darauf noch die Groß-/Kleinschreibung zu ignorieren/ zu beachten.

    Koopakiller - http://koopakiller.ko.ohost.de/

    Donnerstag, 23. Februar 2012 15:23
    Moderator

Alle Antworten

  • Als regulären Ausdruck kannst du @"a\s*b\s*c" wählen:

                string input = "abc def gab cde fga bcd efg";
                string pattern = @"a\s*b\s*c";
    
                Console.WriteLine(Regex.Matches(input, pattern).Count);


    MVP Data Platform Development My blog

    Mittwoch, 22. Februar 2012 18:29
  • Mein Problem liegt leider darin das input ein x-beliebiger Text sein kann.

    Koopakiller - http://koopakiller.ko.ohost.de/

    Mittwoch, 22. Februar 2012 18:32
    Moderator
  • Hallo K.,

    Martins Ansatz ist m.E. eher unabhängig von der Eingabe. Solange Du weißt wonach Du suchst und das Pattern entsprechend anpaßt, werden die Treffer nicht ausbleiben.

    Aber vielleicht erklärst Du auch mal etwas detaillierter was Du eigtl. meinst (ein echtes Beispiel wäre auch nicht verkehrt).

    Gruß
    Marcel

    Donnerstag, 23. Februar 2012 05:51
    Moderator
  • Mein Problem liegt leider darin das input ein x-beliebiger Text sein kann.

    Den input kannst du doch einfach als erstes Argument an die Matches-Methode übergeben, da sehe ich nicht das Problem.

    Wenn du als pattern die Zeichenkette "abc" erhälst, aber dabei Leerzeichen zwischen (und auch vor?) den Zeichen erlauben willst, dann muss man das Pattern erst erstellen, etwa per

                string input = "abc def gab cde fga bcd efg";
                string inputPattern = "abc";
    
                StringBuilder sb = new StringBuilder();
                sb.Append(@"\s*");
                foreach (char c in inputPattern)
                {
                    sb.Append(c);
                    sb.Append(@"\s*");
                }
    
                string pattern = sb.ToString();
                
    
                Console.WriteLine(Regex.Matches(input, pattern).Count);
    Ansonsten musst du detailierter erklären, wie die Zeichenketten aussehen können, die du erhälst, und was genau geprüft werden soll.


    MVP Data Platform Development My blog

    Donnerstag, 23. Februar 2012 11:03
  • Hallo K.,

    das sollte eigentlich mit der Replace-Methode von String oder StringBuilder machbar sein:

                const string input = "abc def gab cde fga bcd efg";
                const string searchPattern = "abc";
                const string replacePattern = "123";
    
                StringBuilder replaced = new StringBuilder(input);
                replaced.Replace(" ", String.Empty);   // Leerzeichen entfernen
                replaced.Replace(searchPattern, replacePattern);
                
                string resultStr = replaced.ToString();
    

    Falls du die Leerzeichen wieder an den alten Positionen eingefügt haben willst, musst du nur die Positionen vorher merken und danach wieder einfügen:

                const string input = "abc def gab cde fga bcd efg";
                const string searchPattern = "abc";
                const string replacePattern = "123";
    
                string[] words = input.Split(' ');   // Positionen merken
    
                StringBuilder replaced = new StringBuilder(input);
                replaced.Replace(" ", String.Empty);
                replaced.Replace(searchPattern, replacePattern);
                
    
    // gemerkte Leerzeichen wieder einfügen
                int startPos = 0;
                foreach (string s in words) {
                    replaced.Insert(startPos + s.Length, ' ');
                    startPos += s.Length + 1;
                }
    
                string resultStr = replaced.ToString();
    

    Dies funktioniert jedoch nur korrekt, wenn der zu ersetzende String gleich lang wie der ersetzte ist.

    Ausserdem stimmt das Ergebnis zwar mit deiner Anforderungsbeschreibung, jedoch nicht mit deinem gewünschten Ergebnis überein, da du in deinem Beispielergebnis auch Leerzeichen die innerhalb des gefundenen Patterns sind, entfernt hast.

    Donnerstag, 23. Februar 2012 14:38
  • Danke für die Hilfe :)Ich habe mal 2 Funktionen geschrieben die genau das macen was ich will:
            private int Matches(string input, string pattern, bool IgnoreCase)
            {
                return Regex.Matches(input.Replace(" ", ""), pattern.Replace(" ", ""), IgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None).Count;
            }
    
            private string Replace(string input, string pattern, string replace, bool IgnoreCase)
            {
                StringBuilder sb = new StringBuilder();
    
                foreach (char c in pattern.Replace(" ", ""))
                {
                    sb.Append(c);
                    sb.Append(@"\s*");
                }
    
                return Regex.Replace(input, sb.ToString().Substring(0, sb.ToString().Length - 3), replace, IgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None);
            }

    Das IgnoreCase bezieht sich darauf noch die Groß-/Kleinschreibung zu ignorieren/ zu beachten.

    Koopakiller - http://koopakiller.ko.ohost.de/

    Donnerstag, 23. Februar 2012 15:23
    Moderator