7
votes

Supprimer Foreach - Optimisation du code C #

Comment optimiser ce code?

Parentdoglist, Childdoglistis - Ilist. Doglistbox - Boîte de liste xxx

EDIT: Parentdogtypelist, chiltypelist a été renommé parentdoglist, enfantdoglist, où les deux ne sont pas liés les uns avec les autres xxx

a été modifié en xxx

Histoire complète:

J'ai besoin de peupler une baisse qui réduirait une relation d'enfant parent. Il y a certains chiens qui peuvent ne pas avoir d'enfant et qui seraient appelés comme unafdog. Et j'ai aussi besoin de montrer le nombre de chiens dans cette catégorie particulière

DD ressemblerait à xxx

donc, la parentdogliste apporterait tout l'enfant et Les éléments de feuilles avec le comte et la chouddoglist auraient le parent et la feuille d'identité d'où je serais en mesure de peupler l'enfant respectif à leur parent et de lier la feuille directement.

Le chien des parents, de l'enfant et de la feuille serait Maintenir dans une table et différencié par StatutId et Count serait dans une autre table.

aucun parent n'aurait aucun compte, seul enfant et feuille n'aurait compter que

Schéma de table:

 texte alt


7 commentaires

Dogtypelist est-il une liste de tous types de chiens et parentdogtypelist un sous-ensemble de types de chiens?


Ces listes sont-elles provenant d'une base de données?


@Sam Safran Ouais les deux listes proviennent de dB.


@Preeet Sangha j'ai plus de 3 forestières intérieures du même genre, donc j'ai pensé à réduire la forise


@Sri, pouvez-vous modifier la question inclure votre schéma de base de données pour les tables ici. une requête directe sera probablement la plus rapide


Vérifier: Si un chien a plus d'un enfant, vous le souhaitez dans la liste de liste plusieurs fois? Votre code semble faire une jointure extérieure.


@Henk Holterman a édité ma question pour expliquer le scénario complet


7 Réponses :


8
votes

Vous pouvez trier parentdoglist et enfantdoglist et faire linéaire O (n) Recherche d'algorithme Insead de ce O (n ^ 2 ) .

Mais vous pouvez trier les conteneurs dans O ((parentdoglist.size () + enfantdoglist.size ()) * log2 (parentdoglist.size () + enfantdoglist.Size ())) . < / p>

Ensuite, si vous exécutez ce code une fois que , votre algorithme est optimal . Mais si vous recherchez plus d'une fois , la solution optimale est trier les conteneurs et effectuer la comparaison en temps linéaire, mais si le conteneur de votre conteneur peut modifier les fonctions de recherche Bettwen a été lanuched et vous utilisez "plus d'une fois Solution de temps "Vous devez utiliser rb-arbre conteneur à Portez ces éléments, car avec une liste normale après que le conteneur a été modifié, vous ne pouvez pas revenir à l'état trié dans O (journal (n)) temps.


0 commentaires

-1
votes
foreach (var ParentDog in ParentDoglist.Where(p=>ChildDoglist.Any(c=>c.Key== p.Key)).ToList())
    dogListBox.Items.Add(new ListItem(ParentDog.Name, ParentDog.Key));
That's how you would do it with LinQ

2 commentaires

Cela n'a-t-il pas encore une boucle imbriquée implicite?


C'est toujours O (n ^ 2) ;-( uniquement avec des vêtements de paresseux dans le conteneur de childdoglist sans aucune optimisation.



2
votes

Votre plus gros problème est probablement le doglistbox.items.add code>. Ajout de chaque élément à un moment est assez coûteux. listbox.items.addrange code> est plus efficace.

Pour rendre la boucle interne beaucoup plus petite, vous pouvez créer une recherche pour les touches de la boucle interne. P>

List<ListItem> listItems = new List<ListItem>();
ILookup<string, Dog> childDogsPerKey = ChildDoglist.ToLookup(dog => dog.Key);
foreach (Dog ParentDog in ParentDoglist)
{
    foreach (Dog ChildDog in childDogsPerKey[ParentDog.Key])
    {
        listItems.Add(new ListItem(ParentDog.Name, ParentDog.Key));
    }
}
dogListBox.Items.AddRange(listItems.ToArray());


1 commentaires

D'accord que Addrange aidera probablement beaucoup.



1
votes

Étant donné que cela vient de la DB, les voyages de la base de données sont susceptibles d'être un tueur de performance. Aussi la comparaison parentdog.key == enfantdog.key code> peut être effectuée dans SQL, de sorte que vous ne tirez pas toutes ces données à votre application pour le jeter.

Redesignez cela pour que vous puissiez Sélectionne unique pour saisir toutes les données dans une requête. P>

ALBIN mentionné Addrange, mais vous pouvez même prendre cela une étape plus loin et virtualiser votre grille afin qu'il ne tire que les rangées affichées à l'utilisateur lorsqu'elle examine cette partie de la grille. p>

EDIT STRT> P>

Pour générer votre liste Il apparaît que vous devez renvoyer quelque chose comme celui-ci à partir de la DB: P>

Parent1, null, null
Parent1, Child1, 110
Parent1, Child12, 12
Parent2, null, null
Parent2, Child21, 23
Parent2, Child22 ,20
Leaf1, null, 20
Leaf2, null, 34


5 commentaires

Modifier ma question pour expliquer le scénario complet


Oui, mais comment remplir la boîte de liste sans boucle?


@SRI, une seule requête et une seule boucle, je ne peux plus m'empêcher de schéma de table et de saveur SQL que vous utilisez (supposant SQL Server)


Mis à jour avec le schéma que j'utilise mysql


J'ai utilisé deux requêtes qui vont chercher le compte pour la feuille et l'enfant. L'autre est utilisé pour obtenir les catégories qui aideraient à trouver quel enfant tombe sous quel parent!



1
votes

Ce n'est pas le forach qui est lent, il ajoute et rendant de nouveaux articles.

Ajouter BeginUpdate / endupdate: p>

dogListBox.BeginUpdate();
foreach (Dog ParentDog in ParentDoglist) 
{ 
 foreach (Dog ChildDog in ChildDoglist) 
 { 
  if(ParentDog.Key==ChildDog.Key) 
  dogListBox.Items.Add(new ListItem(ParentDog.Name, ParentDog.Key)); 
 } 
} 
dogListBox.EndUpdate();


0 commentaires

2
votes

Je pense toujours que la manière la plus élégante et optimisée est d'utiliser Linq pour cela.

box.Items.AddRange(
   ParentDoglist.Join(ChildDoglist, p => p.StatusID, c => c.StatusID, (p,c)=>p)
    .Select(r=>new ListItem(r.StatusID, r.Name)).ToArray());


0 commentaires

0
votes

Vous pouvez remplacer la boucle de forach imbriquée avec une simple expression linq. Pour que cela fonctionne, vous devez utiliser System.Linq; xxx


0 commentaires