6
votes

Rejoindre deux listes de types différents et triez-les par date

J'ai une première liste d'entités comme ceci: xxx

et j'ai une deuxième liste d'entités comme ceci: xxx

Je veux collecter ces deux listes en une et trier tous les éléments par date.

est-ce possible?


3 commentaires

Avez-vous essayé quelque chose? Union de Linq Inscrivez-vous sur Ordonnance, peut vous aider ...


Oui j'ai essayé l'union, mais le problème est de savoir comment les trier car ils n'ont pas le même champ


Vous pouvez Sélectionner à un objet anonyme commun


6 Réponses :


5
votes

Ce problème pourrait facilement être résolu en utilisant du polymorphisme; Utilisez une classe de base commune ou une interface pour les deux classes, qui possède la propriété DateTime code> que vous souhaitez trier.

Exemple: p>

public partial class Networking : EntityBase, INetworking
{
    ...
}

public partial class PrivateNetwork : EntityBase, INetworking
{
    ...
}


6 commentaires

Ce n'est pas vrai (qu'une base commune est requise ); Les objets "Union" peuvent être créés - anonyme ou nommé - qui peut ensuite être commandé sur / stocké. Pas besoin d'une base commune.


@pst alors alors vous finiriez avec une liste d'objets anonymes?


Je suppose qu'il a plus d'entités base sur l'entitébase. Peut-être que cette date n'est pas pertinente pour ces classes.


+1: Alternativement si vous n'avez pas accès à - ou ne pouvez pas changer - entitébase , puis définissez une interface avec la date (et tout ce que vous voulez) dessus et que les deux classes implémentent le Nouvelle interface. Ensuite, vous pouvez lancer les deux séquences sur le type d'interface et trier l'élément de date de l'interface.


@Amiramkorach a raison, toutes mes entités dérivent de l'entitébase et je n'ai pas besoin de date dans les autres classes.


@the_Ruby_raquera ensuite une interface pour les classes dont vous avez besoin la date dans :)



6
votes

Vous pouvez le faire, bien que ce ne soit pas très joli, et vous vous retrouvez avec un iEnumerable code> Vous devez donc vérifier le type de chaque élément avant de pouvoir l'utiliser:

IEnumerable<object> sorted = myNetworkingList
    .Concat<object>(myPrivateNetworkList)
    .OrderBy(n => n is Networking
                 ? (DateTime?)((Networking)n).NetWorkingDate
                 : ((PrivateNetwork)n).DateCreation);

foreach (object either in sorted)
{
    if (either is Networking)
        // Networking; do something
    else
        // PrivateNetwork; do something else
}


7 commentaires

-1: Il s'agit d'une solution laidée et hacky à un problème le mieux résolu avec le polymorphisme. Lorsqu'un troisième Cafewifinetwork est ajouté, il n'y a rien - autre que la mémoire originale Devs ( Mémoire défectueuse ) - pour dire que cette boucle Linq & foreach doit changer. Avec l'une des approches suggérées par @khellang, le compilateur vous obligera à écrire le code correctement. Ça va travailler mais il ne passera aucune critique de code que je ferais partie de.


@Binaire Il n'y a rien de commun entre les deux classes - les propriétés de date ne sont même pas du même type, sans parler du même nom - créant ainsi une interface commune n'est donc pas vraiment polymorphisme, il vient de cacher une opération méchante (trier une liste de la liste de objets non liés) loin dans les classes eux-mêmes plutôt que de la mettre dans le code où le résultat est consommé. Je ne nommerais particulièrement pas l'interface inetworking quand il ne contient rien à voir avec la mise en réseau; C'est plus comme iiarbaryobeBejctThathasanlullableDeTeTeTimeProperty .


Je suis tout à fait en désaccord. Il y a une raison quelconque l'astucieux souhaite fusionner les listes et les trier, ainsi conceptuellement à un niveau ils sont la même chose . L'argument selon lequel les dates sont des "types différents" est faux, DateTime? couvre les deux. Enfin, il n'y a absolument rien de mal à avoir une interface «InetworkingCreateDatedatedatedatedate» avec un seul membre. Même si vous êtes «cachant simplement une opération méchante dans des classes», c'est mieux caché où la relation sera appliquée par le compilateur que dispersé dans divers dur Pour trouver place dans la base de code.


Je viens de voir cela plus comme la requête qui décider de la manière dont il veut trier les objets, plutôt que les objets eux-mêmes se soucient de la manière dont une requête particulière les traite. Évidemment, si les dates avaient un sens sémantique cohérent, je les voudrais abstraité, mais nous ne le savons pas.


«Évidemment, si les dates avaient un sens sémantique cohérent ...» Je pense que le fait que nous trions sur les dates est suffisamment preuves pour un sens sémantique constant. S'il n'y a pas de CSM, cela n'a aucun sens de trier la liste par ces champs. Je pense que nous atteignons un "Nous accepterons de ne pas être d'accord" point dans notre compagnon de conversation.


@BinyWorrier j'ai choisi cette réponse parce que j'ai déjà des enregistrements dans la base de données, donc si je choisis d'ajouter une nouvelle interface Comment traiterai-je les enregistrements déjà stockés avant d'ajouter l'interface?


@the_Ruby_Racer: mec, je ne sais pas comment votre orme fonctionne ou quel effet ajout d'une interface pourrait avoir. Si vous ne peut absolument pas Ajoutez une interface ou une classe de base, vous pouvez toujours le faire polymorphiquement, je vais ajouter une réponse détaillant comment.



1
votes

Créer une interface qui a la date et la mise en œuvre dans les deux classes. Après ce tri, c'est facile.

public interface INetwork
{
    DateTime? Date { get; }
}

public partial class Networking :EntityBase, INetwork
{
    public DateTime? Date
    {
        get { return NetWorkingDate; }
    }
}

public partial class PrivateNetwork :EntityBase, INetwork
{
    public DateTime? Date
    {
        get { return DateCreation; }
    }
}

var commonList = new List<INetwork>();
// Add instances of PrivateNetwork and Networking to the list

var orderedByDate = commonList.OrderBy(n => n.Date);


0 commentaires

2
votes

Ce que j'aurais dû demander plus tôt est. . .

Que voulez-vous faire après les avoir triés?

La réponse à cela pourrait avoir un impact important sur la solution potentielle.

Si la réponse est quelque chose comme Je dois afficher une liste des dates , où vous n'avez besoin que des dates. Si tel est le cas, vous n'avez pas besoin de fusionner les deux listes, vous pouvez obtenir une séquence de juste les dates commandées et l'utiliser, par exemple xxx

si la réponse est Je dois afficher une liste de liens indiquant la date à laquelle des liens vers l'ID de l'objet, ainsi que quelque chose pour identifier le type d'objet , puis vous pouvez vous éloigner de quelque chose de très comme celui ci-dessus, avec un objet anonyme. xxx

Toutefois, si la réponse est je dois envoyer une commande d'arrêt () aux réseaux les plus anciens alors vous avez vraiment besoin d'un Solution polymorphe , où vous avez un seul type que vous pouvez appeler une méthode d'arrêt () sur, qui résoudra à la méthode d'arrêt spécifique () sur le Types de votre utilisation.

une solution polymorphe à utiliser uniquement si l'utilisateur La réponse de Khellang ne fonctionne pas pour vous

d'un commentaire sur une autre réponse

@binyworrier j'ai choisi cette réponse parce que j'ai déjà des enregistrements dans la base de données, donc si je choisis d'ajouter une nouvelle interface comment vais-je traiter Avec les enregistrements déjà stockés avant d'ajouter l'interface?

Je trouve difficile de croire que votre orèse ne vous permettra pas d'ajouter une interface à une classe d'entité et non - Marquez cette interface et / ou son député afin qu'ils soient ignorés par l'ORM .

Cependant, en supposant que vous ne puissiez pas ajouter une nouvelle interface ou une nouvelle classe de base, vous pouvez toujours le faire polymorphiquement.

Ajoutez l'interface, ajoutez une classe implémentant l'interface que pour chaque de vos classes de réseau (les classes abstractor ), puis transformez les classes de réseau en classes abstractor , les ajoutant à une liste et tri et triez cette liste. xxx


1 commentaires

@Kristianhellang: Il y avait un temps où je savais que le livre des motifs en arrière, mais je ne l'ai pas ouvert depuis des années et que je me souviens maintenant des techniques, mais oubliez le nom du modèle ou oubliez que j'ai appris la technique comme un motif. Garçon, je souhaite que mon cerveau fonctionnerait comme il y a 20 ans. . .



0
votes

La première solution utilise le type anonyme xxx pré>

ou sans type anonyme (CustomClass): P>

...
class CustomClass
        {
            public string Name { get; set; }
            public DateTime Date { get; set; }
        }
...
var customCollection = (from human in humans
                                    select new CustomClass
                                        {
                                            Name = human.Name,
                                            Date = human.DateOfBirth,
                                        }
                                        ).Union(from animal in animals
                                                select new CustomClass
                                                    {
                                                        Name = animal.Name,
                                                        Date = animal.DateOfBirth,
                                                    }).OrderBy(x => x.Date);


            foreach (CustomClass customItem in customCollection)
                Console.WriteLine(String.Format("Date: {0}, Name: {1}", customItem.Date, customItem.Name));

...


0 commentaires

0
votes

J'ai simplement ajouté une classe de base et je l'ai attribuée en tant que parent des classes de la fois. Et puis simple l'Union a fait. Cela a fait le tour


0 commentaires