C'è un modo per ottenere una sottostringa con corrispondenza da una stringa utilizzando un confronto di parità sensibile alla cultura? Ad esempio, sotto la cultura en-US, æ
e ae
sono considerati uguali. "Encyclopædia".IndexOf("aed")
valuta 8
, indicando una corrispondenza; tuttavia, esiste un modo per estrarre la sottostringa corrispondente, æd
, che non coinvolga l'iterazione sulla stringa di origine? Si noti che le lunghezze delle sottostringhe ricercate e corrispondenti possono differire di diversi caratteri.Ottieni sottostringa da stringa utilizzando il confronto sensibile alla cultura
6
A
risposta
2
Ho risolto questo problema chiamando per la prima volta IndexOf
per ottenere la posizione iniziale della partita, quindi cercando iterativamente di identificarne la lunghezza. Ho ottimizzato il percorso a caldo della partita avendo la stessa lunghezza della sottostringa specificata; in tal caso, viene eseguito solo un confronto singolo.
public static class StringExtensions
{
public static void Find(this string source, string substring, StringComparison comparisonType, out int matchIndex, out int matchLength)
{
Find(source, substring, 0, source.Length, comparisonType, out matchIndex, out matchLength);
}
public static void Find(this string source, string substring, int searchIndex, StringComparison comparisonType, out int matchIndex, out int matchLength)
{
Find(source, substring, searchIndex, source.Length - searchIndex, comparisonType, out matchIndex, out matchLength);
}
public static void Find(this string source, string substring, int searchIndex, int searchLength, StringComparison comparisonType, out int matchIndex, out int matchLength)
{
matchIndex = source.IndexOf(substring, searchIndex, searchLength, comparisonType);
if (matchIndex == -1)
{
matchLength = -1;
return;
}
matchLength = FindMatchLength(source, substring, searchIndex, searchLength, comparisonType, matchIndex);
// Defensive programming, but should never happen
if (matchLength == -1)
matchIndex = -1;
}
private static int FindMatchLength(string source, string substring, int searchIndex, int searchLength, StringComparison comparisonType, int matchIndex)
{
int matchLengthMaximum = searchLength - (matchIndex - searchIndex);
int matchLengthInitial = Math.Min(substring.Length, matchLengthMaximum);
// Hot path: match length is same as substring length.
if (Compare(source, matchIndex, matchLengthInitial, substring, 0, substring.Length, comparisonType) == 0)
return matchLengthInitial;
int matchLengthDecrementing = matchLengthInitial - 1;
int matchLengthIncrementing = matchLengthInitial + 1;
while (matchLengthDecrementing >= 0 || matchLengthIncrementing <= matchLengthMaximum)
{
if (matchLengthDecrementing >= 0)
{
if (Compare(source, matchIndex, matchLengthDecrementing, substring, 0, substring.Length, comparisonType) == 0)
return matchLengthDecrementing;
matchLengthDecrementing--;
}
if (matchLengthIncrementing <= matchLengthMaximum)
{
if (Compare(source, matchIndex, matchLengthIncrementing, substring, 0, substring.Length, comparisonType) == 0)
return matchLengthIncrementing;
matchLengthIncrementing++;
}
}
// Should never happen
return -1;
}
private static int Compare(string strA, int indexA, int lengthA, string strB, int indexB, int lengthB, StringComparison comparisonType)
{
switch (comparisonType)
{
case StringComparison.CurrentCulture:
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None);
case StringComparison.CurrentCultureIgnoreCase:
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase);
case StringComparison.InvariantCulture:
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None);
case StringComparison.InvariantCultureIgnoreCase:
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase);
case StringComparison.Ordinal:
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.Ordinal);
case StringComparison.OrdinalIgnoreCase:
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.OrdinalIgnoreCase);
default:
throw new ArgumentException("The string comparison type passed in is currently not supported.", nameof(comparisonType));
}
}
}
uso Esempio:
int index, length;
source.Find(remove, StringComparison.CurrentCulture, out index, out length);
string clean = index < 0 ? source : source.Remove(index, length);
Problemi correlati
- 1. Funzione ParseFloat sensibile alla cultura in JavaScript?
- 2. Sottostringa vai alla fine della stringa
- 3. Trova sottostringa in una stringa utilizzando C#
- 4. Ottieni l'indice della sottostringa
- 5. jquery text() non in confronto alla stringa
- 6. Rimozione sottostringa di stringa utilizzando sed
- 7. hashing sensibile alla località - Elasticsearch
- 8. Ottieni sottostringa - tutto prima di determinati caratteri
- 9. Ottieni informazioni cultura preferita/lingua - C#, ASP.NET
- 10. Rimozione della sottostringa da una stringa?
- 11. Idiota rubino per la sottostringa dall'indice alla fine della stringa
- 12. C# Get sottostringa con il modello specifico da stringa
- 13. Ottieni elemento in base alla stringa
- 14. pitone: rimuovere sottostringa solo alla fine della stringa di
- 15. Da dove CultureInfo.CurrentCulture legge cultura
- 16. Formato da decimale a stringa in informazioni cultura corrette
- 17. DateTime formattazione non corrisponde alla cultura
- 18. Ottieni solo l'ora del giorno da DateTime utilizzando il formato 12 o 24 ore come definito dalla cultura corrente
- 19. Elasticsearch corrisponde alla sottostringa in php
- 20. Ingresso tablet sensibile alla pressione in Javafx?
- 21. utilizzando make_tuple per il confronto
- 22. estratto sottostringa utilizzando espressioni regolari in Groovy
- 23. Ottieni la chiave da una HashMap utilizzando il valore
- 24. Confronto dell'accesso alla memoria
- 25. Come impostare Sqlite3 come non sensibile al maiuscolo/minuscolo durante il confronto tra stringhe?
- 26. sottostringa di estratto da NSString
- 27. trovare la sottostringa della stringa
- 28. Ottieni il primo indice di elenco contenente la sottostringa?
- 29. Scopri se la sottostringa sinistra su (i) quando invertita, è uguale alla sottostringa corretta per (i)?
- 30. Come rimuovere una sottostringa particolare da una stringa?
Cosa succede ad usare un'espressione regolare come '(ae | æ) D'? – juharr
@juharr: Regex sarebbe eccessivo (e introdurrà la propria serie di sfumature). Ho bisogno di questo per implementare funzionalità molto generali, come un metodo di estensione 'String.Replace' sensibile alla cultura. – Douglas
Domande correlate: [Come posso eseguire un'operazione "start-in" sensibile alla cultura dal centro di una stringa?] (Http://stackoverflow.com/q/15980310/1149773) (di Jon Skeet), [Lunghezza della sottostringa corrispondente al metodo 'String.IndexOf' sensibile alla cultura] (http://stackoverflow.com/q/20480016/1149773). – Douglas