Dizionario sensibile alle maiuscole / minuscole con chiave-tipo di stringa in C #


156

Se ho un Dictionary<String,...>è possibile rendere metodi come ContainsKeymaiuscole e minuscole?

Sembrava correlato, ma non l'ho capito bene: Dizionario c #: rendere il Key insensibile al maiuscolo / minuscolo attraverso le dichiarazioni


6
Cosa c'è di sbagliato nell'uso StringComparer.InvariantCultureIgnoreCase? Fa quello che dice ...
leppie il

5
Non ne avevo mai sentito parlare, quindi la domanda!
Mr. Boy,


Questa domanda è collegata, ma non del tutto duplicata di questa. Quello spiega come gestire un dizionario esistente. Sto iniziando con un nuovo codice, quindi le risposte qui sono più adatte.
arrivederci,

Risposte:


322

Sembrava correlato, ma non l'ho capito bene: Dizionario c #: rendere il Key insensibile al maiuscolo / minuscolo attraverso le dichiarazioni

È effettivamente correlato. La soluzione è dire all'istanza del dizionario di non usare il metodo di confronto di stringhe standard (che fa distinzione tra maiuscole e minuscole) ma piuttosto di usare un metodo senza distinzione tra maiuscole e minuscole. Questo viene fatto usando il costruttore appropriato :

var dict = new Dictionary<string, YourClass>(
        StringComparer.InvariantCultureIgnoreCase);

Il costruttore si aspetta uno IEqualityComparerche indichi al dizionario come confrontare le chiavi.

StringComparer.InvariantCultureIgnoreCaseti dà IEqualityComparerun'istanza che confronta le stringhe in modo insensibile al maiuscolo / minuscolo.


1
Perfetto, in qualche modo mi era sfuggito il modo simile a STL di passare il comparatore nel ctor.
Mr. Boy,

7
Non smette mai di stupirmi di come trovo sempre la risposta a qualsiasi domanda di programmazione qui! Forse chiamerò il mio prossimo gatto come te, Konrad! :-)
Jamie,

10
Possibile, l'operatore di confronto StringComparison.OrdinalIgnoreCase più velocemente di quanto la cultura-based: stackoverflow.com/questions/492799/...
Manushin Igor

Come posso farlo se non sto creando un dizionario ma sto cercando di usare ContainsKey () per una corrispondenza di chiave senza distinzione tra maiuscole e minuscole su un dizionario esistente che ottengo come parte di un oggetto?
Shridhar R Kulkarni,

1
@ShridharRKulkarni Fondamentalmente non puoi (in modo efficiente). La logica di confronto è una parte fondamentale della struttura dei dati del dizionario interno. Per consentire ciò, il contenitore dovrebbe mantenere più indici per i suoi dati e i dizionari non lo fanno.
Konrad Rudolph,

21
var myDic = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
myDic.Add("HeLlo", "hi");

if (myDic.ContainsKey("hello"))
    Console.WriteLine(myDic["hello"]);

1
Lo snippet di codice dice tutto. Molto utile. Non sono sicuro del motivo per cui questo post ha così meno voti rispetto alla risposta accettata solo per il ritardo di 3 minuti.
RBT

14

Ci sono poche possibilità in cui il tuo affare con il dizionario viene estratto da terze parti o da una DLL esterna. Usando linq

YourDictionary.Any(i => i.KeyName.ToLower().Contains("yourstring")))


3
Funziona benissimo. Un avvertimento però, se cambi Anya SingleOrDefaultte non nulltornerai se non esiste, invece otterrai una coppia chiave di valore con chiave e valore impostati su null!
NibblyPig

1
ContainsSembra un caso d'uso molto specifico di qualcosa su cui stavi lavorando in quel momento. Come risposta utile più generica, penso Equalssia meglio. E su quella stessa nota, invece di duplicare una stringa con ToLower(), sarebbe ancora meglio usare StringComparison.xxxCase.
Suamere,

1
questo è stato molto utile e sbarazzarsi di ToLower è sicuramente un miglioramento - il mio caso d'uso è stato: return AppliedBuffs.Any (b => b.Key.Equals (Name, StringComparison.OrdinalIgnoreCase)); un insensibile al maiuscolo / minuscolo perfetto Contiene un dizionario sensibile al maiuscolo / minuscolo.
David Burford,

Sono così tentato di votare questo. Un avvertimento, se sei il proprietario del dizionario, questo non è certamente il modo di farlo. Usa questo approccio solo se non sai come è stata istanziata il dizionario. Anche in questo caso, per una corrispondenza esatta della stringa (non solo una corrispondenza parziale), utilizzare il dict.Keys.Contains("bla", appropriate comparer)sovraccarico LINQ per facilità d'uso.
nawfal,

1

Ho appena incontrato lo stesso tipo di problema in cui avevo bisogno di un dizionario sensibile alle maiuscole / minuscole in un controller ASP.NET Core.

Ho scritto un metodo di estensione che fa il trucco. Forse questo può essere utile anche per gli altri ...

public static IDictionary<string, TValue> ConvertToCaseInSensitive<TValue>(this IDictionary<string, TValue> dictionary)
{
    var resultDictionary = new Dictionary<string, TValue>(StringComparer.InvariantCultureIgnoreCase);
    foreach (var (key, value) in dictionary)
    {
        resultDictionary.Add(key, value);
    }

    dictionary = resultDictionary;
    return dictionary;
}

Per utilizzare il metodo di estensione:

myDictionary.ConvertToCaseInSensitive();

Quindi ottieni un valore dal dizionario con:

myDictionary.ContainsKey("TheKeyWhichIsNotCaseSensitiveAnymore!");

0

Se non hai alcun controllo nella creazione dell'istanza, supponiamo che il tuo oggetto sia desterilizzato da json ecc., Puoi creare una classe wrapper che eredita dalla classe del dizionario.

public class CaseInSensitiveDictionary<TValue> : Dictionary<string, TValue>
{
    public CaseInSensitiveDictionary() : base(StringComparer.OrdinalIgnoreCase){}
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.