J'utilise un Dictionary<string, int>
où leint
est un compte de la clé.
Maintenant, j'ai besoin d'accéder à la dernière clé insérée dans le dictionnaire, mais je n'en connais pas le nom. La tentative évidente:
int LastCount = mydict[mydict.keys[mydict.keys.Count]];
ne fonctionne pas, car Dictionary.Keys
n'implémente pas un [] -indexer.
Je me demande simplement s'il existe une classe similaire? J'ai pensé à utiliser une pile, mais cela ne stocke qu'une chaîne. Je pourrais maintenant créer ma propre structure et ensuite utiliser a Stack<MyStruct>
, mais je me demande s'il existe une autre alternative, essentiellement un dictionnaire qui implémente un [] -indexer sur les clés?
c#
.net
dictionary
Michael Stum
la source
la source
Réponses:
Comme @Falanwe le souligne dans un commentaire, faire quelque chose comme ça est incorrect :
Vous ne devez pas dépendre de l'ordre des clés dans un dictionnaire. Si vous avez besoin d'une commande, vous devez utiliser un OrderedDictionary , comme suggéré dans cette réponse . Les autres réponses sur cette page sont également intéressantes.
la source
HashTable
System.Collections.ICollection 'ne contient pas de définition pour' ElementAt 'et aucune méthode d'extension' ElementAt 'acceptant un premier argument de type' System.Collections.ICollection 'n'a pu être trouvéeElementAtOrDefault
version pour travailler avec la version sans exception.Dictionary<TKey,TValue>
documentation , "l'ordre des clés dans leDictionary<TKey, TValue>.KeyCollection
n'est pas spécifié." L'ordre étant indéfini, vous n'avez aucun moyen de savoir avec certitude qui est à la dernière position (mydict.Count -1
)Vous pouvez utiliser un OrderedDictionary .
la source
Un dictionnaire est une table de hachage, vous n'avez donc aucune idée de l'ordre d'insertion!
Si vous voulez connaître la dernière clé insérée, je suggère d'étendre le dictionnaire pour inclure une valeur LastKeyInserted.
Par exemple:
Vous rencontrerez des problèmes, cependant lorsque vous l'utiliserez
.Remove()
, vous devrez donc conserver une liste ordonnée des clés insérées.la source
Pourquoi ne pas étendre simplement la classe de dictionnaire pour ajouter une dernière propriété clé insérée. Quelque chose comme ce qui suit peut-être?
la source
Vous pouvez toujours faire ceci:
Mais je ne le recommanderais pas. Il n'y a aucune garantie que la dernière clé insérée sera à la fin du tableau. La commande des clés sur MSDN n'est pas spécifiée et peut être modifiée. Dans mon très bref test, cela semble être dans l'ordre d'insertion, mais vous feriez mieux de créer une comptabilité appropriée comme une pile - comme vous le suggérez (bien que je ne vois pas la nécessité d'une structure basée sur votre autres instructions) - ou cache de variable unique si vous avez juste besoin de connaître la dernière clé.
la source
Je pense que vous pouvez faire quelque chose comme ça, la syntaxe est peut-être erronée, vous n'avez pas utilisé C # depuis un moment Pour obtenir le dernier élément
ou utilisez Max au lieu de Last pour obtenir la valeur maximale, je ne sais pas lequel correspond le mieux à votre code.
la source
Je suis d'accord avec la deuxième partie de la réponse de Patrick. Même si dans certains tests, il semble conserver l'ordre d'insertion, la documentation (et le comportement normal des dictionnaires et des hachages) indique explicitement que l'ordre n'est pas spécifié.
Vous demandez simplement des problèmes en fonction de la commande des clés. Ajoutez votre propre comptabilité (comme Patrick l'a dit, juste une seule variable pour la dernière clé ajoutée) pour être sûr. Aussi, ne vous laissez pas tenter par toutes les méthodes telles que Last et Max sur le dictionnaire car elles sont probablement liées au comparateur clé (je ne suis pas sûr de cela).
la source
Dans le cas où vous décidez d'utiliser un code dangereux qui est sujet à rupture, cette fonction d'extension récupérera une clé de a en
Dictionary<K,V>
fonction de son indexation interne (qui pour Mono et .NET semble actuellement être dans le même ordre que vous obtenez en énumérant laKeys
propriété ).Il est de loin préférable d'utiliser Linq:,
dict.Keys.ElementAt(i)
mais cette fonction itérera O (N); ce qui suit est O (1) mais avec une pénalité de performance de réflexion.la source
Une alternative serait un KeyedCollection si la clé est incorporée dans la valeur.
Créez simplement une implémentation de base dans une classe scellée à utiliser.
Donc pour remplacer
Dictionary<string, int>
(ce qui n'est pas un très bon exemple car il n'y a pas de clé claire pour un int).la source
La façon dont vous avez formulé la question me porte à croire que l'int dans le dictionnaire contient la "position" de l'élément dans le dictionnaire. À en juger par l'affirmation selon laquelle les clés ne sont pas stockées dans l'ordre dans lequel elles ont été ajoutées, si cela est correct, cela signifierait que keys.Count (ou .Count - 1, si vous utilisez une base zéro) devrait toujours toujours être le numéro de la dernière clé saisie?
Si c'est correct, y a-t-il une raison pour laquelle vous ne pouvez pas utiliser à la place Dictionary <int, string> pour pouvoir utiliser mydict [mydict.Keys.Count]?
la source
Je ne sais pas si cela fonctionnerait parce que je suis à peu près sûr que les clés ne sont pas stockées dans l'ordre dans lequel elles sont ajoutées, mais vous pouvez convertir KeysCollection dans une liste, puis obtenir la dernière clé de la liste ... mais ça vaudrait la peine d'y jeter un œil.
La seule autre chose à laquelle je peux penser est de stocker les clés dans une liste de recherche et d'ajouter les clés à la liste avant de les ajouter au dictionnaire ... ce n'est pas joli.
la source
Pour développer l'article de Daniels et ses commentaires concernant la clé, puisque la clé est de toute façon intégrée dans la valeur, vous pouvez recourir à l'utilisation d'un
KeyValuePair<TKey, TValue>
comme valeur. Le raisonnement principal en est que, en général, la clé n'est pas nécessairement directement dérivable de la valeur.Ensuite, cela ressemblerait à ceci:
Pour utiliser ceci comme dans l'exemple précédent, vous feriez:
la source
Un dictionnaire peut ne pas être très intuitif pour utiliser l'index comme référence, mais vous pouvez avoir des opérations similaires avec un tableau de KeyValuePair :
ex.
KeyValuePair<string, string>[] filters;
la source
Vous pouvez également utiliser SortedList et son équivalent générique. Ces deux classes et dans la réponse d'Andrew Peters mentionnées OrderedDictionary sont des classes de dictionnaire dans lesquelles les éléments sont accessibles par index (position) ainsi que par clé. Comment utiliser ces classes, vous pouvez trouver: Classe SortedList , Classe générique SortedList .
la source
UserVoice de Visual Studio donne un lien vers l' implémentation générique OrderedDictionary par dotmore.
Mais si vous avez seulement besoin d'obtenir des paires clé / valeur par index et que vous n'avez pas besoin d'obtenir des valeurs par clés, vous pouvez utiliser une astuce simple. Déclarez une classe générique (je l'ai appelée ListArray) comme suit:
Vous pouvez également le déclarer avec des constructeurs:
Par exemple, vous lisez certaines paires clé / valeur d'un fichier et souhaitez simplement les stocker dans l'ordre dans lequel elles ont été lues afin de les obtenir plus tard par index:
Comme vous l'avez peut-être remarqué, vous ne pouvez pas nécessairement avoir uniquement des paires clé / valeur dans votre ListArray. Les tableaux d'éléments peuvent être de n'importe quelle longueur, comme dans un tableau irrégulier.
la source