Ich habe eine große Zeichenfolge, die ich analysieren muss, und ich muss alle Instanzen von extract"(me,i-have lots. of]punctuation
finden und den Index von jeder in einer Liste speichern.
Angenommen, dieses Stück Zeichenfolge befand sich am Anfang und in der Mitte der größeren Zeichenfolge. Beide würden gefunden und ihre Indizes würden zu der hinzugefügt List
. und der List
würde enthalten 0
und der andere Index, was auch immer es sein würde.
Ich habe herumgespielt und das string.IndexOf
macht fast das, wonach ich suche, und ich habe Code geschrieben - aber es funktioniert nicht und ich konnte nicht genau herausfinden, was falsch ist:
List<int> inst = new List<int>();
int index = 0;
while (index < source.LastIndexOf("extract\"(me,i-have lots. of]punctuation", 0) + 39)
{
int src = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index);
inst.Add(src);
index = src + 40;
}
inst
= Die Listesource
= Die große Zeichenfolge
Irgendwelche besseren Ideen?
yield
wird der Code "faul". Es werden nicht alle Indizes in einer speicherinternen Liste innerhalb der Methode gesammelt. Welche praktischen Auswirkungen dies auf die Leistung hat, hängt von vielen Faktoren ab.value.Length
Sie verschachtelte Übereinstimmungen verpassen! Beispiel: "Dies ist ein NestedNestedNested-Match-Test!" Bei Übereinstimmung mit "NestedNested" wird nur ein Index gefunden, nicht jedoch der verschachtelte. Um dies zu beheben, fügen Sie statt+=1
in einfach eine Schleife hinzu+=value.Length
.Warum verwenden Sie nicht die integrierte RegEx-Klasse:
public static IEnumerable<int> GetAllIndexes(this string source, string matchString) { matchString = Regex.Escape(matchString); foreach (Match match in Regex.Matches(source, matchString)) { yield return match.Index; } }
Wenn Sie den Ausdruck wiederverwenden müssen, kompilieren Sie ihn und speichern Sie ihn irgendwo zwischen. Ändern Sie den Parameter matchString in einen Regex-MatchExpression in einer anderen Überladung für den Wiederverwendungsfall.
quelle
indexes
? Es ist nirgendwo definiert.mit LINQ
public static IEnumerable<int> IndexOfAll(this string sourceString, string subString) { return Regex.Matches(sourceString, subString).Cast<Match>().Select(m => m.Index); }
quelle
Polierte Version + Gehäuse ohne Unterstützung:
public static int[] AllIndexesOf(string str, string substr, bool ignoreCase = false) { if (string.IsNullOrWhiteSpace(str) || string.IsNullOrWhiteSpace(substr)) { throw new ArgumentException("String or substring is not specified."); } var indexes = new List<int>(); int index = 0; while ((index = str.IndexOf(substr, index, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) != -1) { indexes.Add(index++); } return indexes.ToArray(); }
quelle
Dies könnte in effizienter Zeitkomplexität unter Verwendung des KMP- Algorithmus in O (N + M) erfolgen, wobei N die Länge von
text
und M die Länge von istpattern
.Dies ist die Implementierung und Verwendung:
static class StringExtensions { public static IEnumerable<int> AllIndicesOf(this string text, string pattern) { if (string.IsNullOrEmpty(pattern)) { throw new ArgumentNullException(nameof(pattern)); } return Kmp(text, pattern); } private static IEnumerable<int> Kmp(string text, string pattern) { int M = pattern.Length; int N = text.Length; int[] lps = LongestPrefixSuffix(pattern); int i = 0, j = 0; while (i < N) { if (pattern[j] == text[i]) { j++; i++; } if (j == M) { yield return i - j; j = lps[j - 1]; } else if (i < N && pattern[j] != text[i]) { if (j != 0) { j = lps[j - 1]; } else { i++; } } } } private static int[] LongestPrefixSuffix(string pattern) { int[] lps = new int[pattern.Length]; int length = 0; int i = 1; while (i < pattern.Length) { if (pattern[i] == pattern[length]) { length++; lps[i] = length; i++; } else { if (length != 0) { length = lps[length - 1]; } else { lps[i] = length; i++; } } } return lps; }
und dies ist ein Beispiel für die Verwendung:
static void Main(string[] args) { string text = "this is a test"; string pattern = "is"; foreach (var index in text.AllIndicesOf(pattern)) { Console.WriteLine(index); // 2 5 } }
quelle
public List<int> GetPositions(string source, string searchString) { List<int> ret = new List<int>(); int len = searchString.Length; int start = -len; while (true) { start = source.IndexOf(searchString, start + len); if (start == -1) { break; } else { ret.Add(start); } } return ret; }
Nennen Sie es so:
List<int> list = GetPositions("bob is a chowder head bob bob sldfjl", "bob"); // list will contain 0, 22, 26
quelle
Hallo nette Antwort von @Matti Virkkunen
public static List<int> AllIndexesOf(this string str, string value) { if (String.IsNullOrEmpty(value)) throw new ArgumentException("the string to find may not be empty", "value"); List<int> indexes = new List<int>(); for (int index = 0;; index += value.Length) { index = str.IndexOf(value, index); if (index == -1) return indexes; indexes.Add(index); index--; } }
Dies umfasst jedoch Testfälle wie AOOAOOA, bei denen Teilzeichenfolgen verwendet werden
sind AOOA und AOOA
Ausgang 0 und 3
quelle
Verwenden Sie ohne Regex den Zeichenfolgenvergleichstyp:
string search = "123aa456AA789bb9991AACAA"; string pattern = "AA"; Enumerable.Range(0, search.Length) .Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; }) .Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length),StringComparison.OrdinalIgnoreCase)) .Select(searchbit => searchbit.Index)
Dies gibt {3,8,19,22} zurück. Ein leeres Muster würde allen Positionen entsprechen.
Für mehrere Muster:
string search = "123aa456AA789bb9991AACAA"; string[] patterns = new string[] { "aa", "99" }; patterns.SelectMany(pattern => Enumerable.Range(0, search.Length) .Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; }) .Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length), StringComparison.OrdinalIgnoreCase)) .Select(searchbit => searchbit.Index))
Dies gibt {3, 8, 19, 22, 15, 16} zurück.
quelle
@csam ist theoretisch korrekt, obwohl sein Code nicht den Anforderungen entspricht und zu refraktärisiert werden kann
public static IEnumerable<int> IndexOfAll(this string sourceString, string matchString) { matchString = Regex.Escape(matchString); return from Match match in Regex.Matches(sourceString, matchString) select match.Index; }
quelle
Ich habe festgestellt, dass mindestens zwei vorgeschlagene Lösungen keine überlappenden Suchtreffer verarbeiten. Ich habe den mit dem grünen Häkchen gekennzeichneten nicht überprüft. Hier ist eine, die überlappende Suchtreffer behandelt:
public static List<int> GetPositions(this string source, string searchString) { List<int> ret = new List<int>(); int len = searchString.Length; int start = -1; while (true) { start = source.IndexOf(searchString, start +1); if (start == -1) { break; } else { ret.Add(start); } } return ret; }
quelle
public static Dictionary<string, IEnumerable<int>> GetWordsPositions(this string input, string[] Susbtrings) { Dictionary<string, IEnumerable<int>> WordsPositions = new Dictionary<string, IEnumerable<int>>(); IEnumerable<int> IndexOfAll = null; foreach (string st in Susbtrings) { IndexOfAll = Regex.Matches(input, st).Cast<Match>().Select(m => m.Index); WordsPositions.Add(st, IndexOfAll); } return WordsPositions; }
quelle
Basierend auf dem Code, den ich zum Suchen mehrerer Instanzen einer Zeichenfolge in einer größeren Zeichenfolge verwendet habe, sieht Ihr Code folgendermaßen aus:
List<int> inst = new List<int>(); int index = 0; while (index >=0) { index = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index); inst.Add(index); index++; }
quelle
indexOf
-1 und der zurückgegeben werdenindex++
. Ich würde awhile (true)
mit a verwenden,break;
wenn das Ergebnis vonIndexOf
-1 ist.Ich habe dieses Beispiel gefunden und in eine Funktion integriert:
public static int solution1(int A, int B) { // Check if A and B are in [0...999,999,999] if ( (A >= 0 && A <= 999999999) && (B >= 0 && B <= 999999999)) { if (A == 0 && B == 0) { return 0; } // Make sure A < B if (A < B) { // Convert A and B to strings string a = A.ToString(); string b = B.ToString(); int index = 0; // See if A is a substring of B if (b.Contains(a)) { // Find index where A is if (b.IndexOf(a) != -1) { while ((index = b.IndexOf(a, index)) != -1) { Console.WriteLine(A + " found at position " + index); index++; } Console.ReadLine(); return b.IndexOf(a); } else return -1; } else { Console.WriteLine(A + " is not in " + B + "."); Console.ReadLine(); return -1; } } else { Console.WriteLine(A + " must be less than " + B + "."); // Console.ReadLine(); return -1; } } else { Console.WriteLine("A or B is out of range."); //Console.ReadLine(); return -1; } } static void Main(string[] args) { int A = 53, B = 1953786; int C = 78, D = 195378678; int E = 57, F = 153786; solution1(A, B); solution1(C, D); solution1(E, F); Console.WriteLine(); }
Kehrt zurück:
53 an Position 2 gefunden
78 an Position 4 gefunden
78 gefunden an Position 7
57 ist nicht in 153786
quelle