J'écris un programme pour définir une séquence dans laquelle divers objets apparaîtront dans le rapport. La séquence est la position Y (cellule) sur la feuille de calcul Excel.
Une partie démo du code est ci-dessous. Ce que je veux accomplir est d'avoir une collection, ce qui me permettra d'ajouter plusieurs objets et je pourrai obtenir une collection triée en fonction de la séquence
SortedList list = new SortedList();
Header h = new Header();
h.XPos = 1;
h.name = "Header_1";
list.Add(h.XPos, h);
h = new Header();
h.XPos = 1;
h.name = "Header_2";
list.Add(h.XPos, h);
Je sais que le SortedList
ne permettra pas cela et j'ai cherché une alternative. Je ne veux pas éliminer les doublons et déjà essayé List<KeyValuePair<int, object>>
.
Merci.
c#
.net
linq
collections
sortedlist
Mayur Kotlikar
la source
la source
List
?Réponses:
Utilisez votre propre IComparer!
Comme déjà indiqué dans d'autres réponses, vous devez utiliser votre propre classe de comparaison. Pour cela, j'utilise une classe IComparer générique, qui fonctionne avec tout ce qui implémente IComparable:
Vous l'utiliserez lors de l'instanciation d'une nouvelle SortedList, SortedDictionary etc:
Ici, int est la clé qui peut être dupliquée.
la source
SortedDictionary
. Il permet également le retrait.Vous pouvez utiliser List <> en toute sécurité. La liste a une méthode Sort, dont une surcharge accepte IComparer. Vous pouvez créer votre propre classe de tri au format. Voici un exemple:
la source
J'utilise ce qui suit:
Mon cas de test:
Le résultat:
la source
Le problème est que la conception de la structure de données ne correspond pas aux exigences: il est nécessaire de stocker plusieurs en-têtes pour le même XPos. Par conséquent,
SortedList<XPos, value>
ne doit pas avoir une valeur deHeader
, mais une valeur deList<Header>
. C'est un changement simple et léger, mais il résout tous les problèmes et évite de créer de nouveaux problèmes comme d'autres solutions suggérées (voir l'explication ci-dessous):Veuillez noter que l'ajout d'une touche "drôle", comme ajouter un nombre aléatoire ou prétendre que 2 XPos avec la même valeur sont différents, conduit à de nombreux autres problèmes. Par exemple, il devient difficile voire impossible de supprimer un en-tête particulier.
Notez également que les performances de tri sont bien meilleures si seulement quelques
List<Header>
- uns doivent être triés que tousHeader
. Exemple: s'il y a 100 XPos et que chacun a 100 en-têtes, 10000Header
doivent être triés au lieu de 100List<Header>
.Bien sûr, cette solution a également un inconvénient: s'il y a beaucoup de XPos avec seulement 1 en-tête, autant de listes doivent être créées, ce qui est une surcharge.
la source
Solution la plus simple (par rapport à tout ce qui précède): utilisez
SortedSet<T>
, il accepte uneIComparer<SortableKey>
classe, puis implémentez la méthode Compare de cette façon:la source
Merci beaucoup pour votre aide. En cherchant plus, j'ai trouvé cette solution. (Disponible sur Stackoverflow.com dans une autre question)
Tout d'abord, j'ai créé une classe qui encapsulerait mes objets pour les classes (en-têtes, pied de page, etc.)
Donc, cette classe est censée tenir sur les objets, et PosX de chaque objet va comme int Position
Ce que j'obtiens finalement, c'est la liste triée "Séquence".
la source
Avez-vous essayé
Lookup<TKey, TElement>
qui autorisera les clés en double http://msdn.microsoft.com/en-us/library/bb460184.aspxla source
Lookup
je crois qu'il n'y a pas de constructeur public . Un bon moyen de contourner cela?ToLookup
sur n'importe quelIEnumerable<T>
.Vous pouvez utiliser la SortedList, utiliser votre valeur pour la TKey et int (count) pour la TValue.
Voici un exemple: une fonction qui trie les lettres d'un mot.
la source
Cette classe de collection conservera les doublons et insérera un ordre de tri pour le duplicata. L'astuce consiste à étiqueter les éléments avec une valeur unique lorsqu'ils sont insérés pour maintenir un ordre de tri stable. Ensuite, nous enveloppons le tout dans une interface ICollection.
une classe de test
La structure de balisage
L'assistant de comparaison lambda
la source
Le problème est que vous utilisez quelque chose comme clé qui n'est pas une clé (car cela se produit plusieurs fois).
Donc, si vous avez de vraies coordonnées, vous devriez peut-être prendre le
Point
comme clé de votre SortedList.Ou vous créez un
List<List<Header>>
où votre premier index de liste définit la position x et l'index de liste interne la position y (ou vice versa si vous le souhaitez).la source
La clé (jeu de mots) pour cela est de créer une
IComparable
classe basée sur l'égalité et le hachage, mais qui ne se compare jamais à 0 si elle n'est pas égale. Cela peut être fait et peut être créé avec quelques bonus - un tri stable (c'est-à-dire que les valeurs ajoutées en premier à la liste triée conserveront leur position), etToString()
peut simplement renvoyer la valeur réelle de la chaîne de clé.Voici une clé struct qui devrait faire l'affaire:
la source
Linq.Lookup est cool et tout, mais si votre cible est simplement de boucler sur les "clés" tout en leur permettant d'être dupliquées, vous pouvez utiliser cette structure:
Ensuite, vous pouvez écrire:
HTH
la source
L'astuce consiste à augmenter votre objet avec une clé unique. Voir le test suivant qui réussit. Je souhaite que mes points soient triés en fonction de leur valeur X. Le simple fait d'utiliser un Point2D nu dans ma fonction de comparaison entraînera l'élimination des points avec la même valeur X. J'emballe donc le Point2D dans une classe de marquage appelée Indexed.
Les utilitaires pour faire ce travail sont
Un comparateur qui prend un lambda
Une structure de balisage
la source
C'est ainsi que j'ai résolu le problème. Il est censé être thread-safe, bien que vous puissiez simplement supprimer les
lock
s si vous n'en avez pas besoin. Notez également que l'arbitraireInsert
à un index n'est pas pris en charge car cela pourrait violer la condition de tri.la source
Créez une classe et interrogez la liste:
la source
Voici mon point de vue à ce sujet. Attention, voici peut-être des dragons, C # encore assez nouveau pour moi.
Usage:
la source
Queue
dans BCL, qui représente une collection d'éléments premier entré, premier sorti. La sémantique de votre classe est différente. Votre classe a un début (où les éléments sont retirés de la file d'attente) mais pas de fin (un élément peut être inséré n'importe où). Donc, laEnqueue
méthode dans votre classe n'a aucun sens à mon humble avis.PriorityQueue
serait donc un nom plus approprié.-2 * 5 == +10
), donc ce n'est pas un gros problème. :-)