8
votes

C # Vitesse d'expression Lambda

Je n'ai pas utilisé de nombreuses expressions de Lambda avant et j'ai couru dans un cas où je pensais pouvoir utiliser une utilisation slick d'une. J'ai une liste personnalisée de 19 000 enregistrements et j'ai besoin de savoir si un enregistrement existe ou non dans la liste, au lieu d'écrire un tas de boucles ou d'utiliser LINQ pour passer à travers la liste que j'ai décidé d'essayer ceci:

for (int i = MinX; i <= MaxX; ++i)
{
    tempY = MinY;

    while (tempY <= MaxY)
    {
        bool exists = myList.Exists(item => item.XCoord == i && item.YCoord == tempY);

        ++tempY;
    }
}


4 commentaires

Pourquoi espérez-vous que cela soit rapide? C'est une recherche imbriquée sans aucune sorte d'indexation ou de tri.


Je ne pense pas que le vote au bas soit nécessaire. C'est un problème intéressant, bien que mal formulé.


Pourquoi la boucle extérieure a-t-elle A pour la boucle, mais la boucle intérieure de temps?


Je peux donc faire boucle à travers toutes les coordonnées X, puis en boucle à travers toutes les coordonnées y. Par exemple, pensez à chaque x en tant que colonne et chaque y comme rangée et j'essaie de boucler toutes les cellules de cette colonne.


5 Réponses :


7
votes

Ce n'est pas un problème avec la Lambda, c'est un problème avec votre algorithme. Vous êtes en boucle de Minx à MaxX, c'est-à-dire combien? Ensuite, vous êtes en boucle à travers la même chose de Minie à Maxy, alors vous en boucle à travers ~ 19 000 enregistrements. Donc, si la boucle X est 10 et la boucle Y a 10 ans, vous faites des appels de 19 000 * 10 * 10. Cela pourrait être beaucoup pire.


0 commentaires

6
votes

Votre algorithme est inefficace. Si vous effectuez plusieurs recherches sur la même liste, vous devez:

  1. Trier la liste de manière appropriée (par votre clé de recherche).
  2. Utilisez un Recherche binaire pour trouver le bon enregistrement.

    Votre autre option est si la mémoire n'est pas un problème et que vous souhaitez qu'il soit vraiment rapide, c'est de mettre les enregistrements dans un dictionnaire . Cela vous donnera l'accès le plus rapide après avoir été configuré.


1 commentaires

Cela a vraiment bien fonctionné. N'a pris que 1 seconde pour faire ce que je voulais.



2
votes

N'est-ce pas ce que vous voulez?

myList.Where(
    item=>item.XCoord>=MinX
        &&item.XCoord<=MaxX
        &&item.YCoord>=MinY
        &&item.YCoord<=MaxY
)


0 commentaires

12
votes

Ce code ne donne aucun sens pour moi, il est donc vraiment difficile de dire si vous le faites mal ou non. Les chances sont bonnes que oui, vous le faites mal.

Plutôt que de montrer le code, essayez ceci. Supposons que vous ayez une méthode exactement ce que vous voulez. Que serait la la signature de cette méthode? Pas le corps, juste la signature.

Supposons par exemple que vous souhaitez poser la question "Cette liste de points contient-elle un point particulier?" Ensuite, la signature serait xxx

supposons que vous souhaitez poser la question "Cette liste de points contient-il un point à l'intérieur de ce rectangle?" Ensuite, la signature serait xxx

supposons que vous souhaitez poser la question "Quels sont les points que ces deux listes ont en commun?" Ensuite, la signature serait xxx

et ainsi de suite. Indiquez ce que vous essayez de faire plus clairement et nous pouvons vous aider à optimiser cette opération. Commencez avec la signature.


1 commentaires

+1 Parce qu'il ressemble vraiment à Nathan crée manuellement point , lorsqu'il pourrait vraiment stocker une liste générique de points et utiliser contient .



1
votes

Je vais développer la réponse de Kevin avec une belle solution à base de Linq.

Le code d'origine a effectivement calculé efficacement une matrice booléenne en deux dimensions indiquant si une coordonnée existait dans myList au < Code> x & y coordonnées pour chaque élément de tableau.

Le test utilisé pour chaque x & y Peut être exprimé en tant que fonction Lambda en tant que telle: xxx

Ceci est inefficace car le existe est appelé, et donc la liste est itérale, Pour chaque x & y coordonné testé. Que la liste complète est itératée dépend ou non si une correspondance est trouvée ou non. Dans beaucoup de cas, il n'y aura pas de correspondance afin que toute la liste soit visitée plusieurs fois.

Il est donc préférable de pré-calculer un dictionnaire de dictionnaires pour déterminer si une coordonnée existe dans MyList pour tout x & y coordonnée. xxx

xylookup maintenant permet la fonction Lambda suivante de remplacer la version d'origine. xxx

pré-calcul xylookup prend du temps donc, selon mes tests, si j'ai Un tableau 3x3 et MyList contient 3 coordonnées. Les deux méthodes sont à peu près la même vitesse. Je m'attendrais à ce que la taille réelle de la matrice et le nombre d'éléments dans myList serait beaucoup plus vaste dans la pratique.

Si j'ai un tableau 100x100 avec 10 000 coordonnées dans MyList (code> xylookup est environ 91 fois plus rapide que la méthode d'origine.

J'aime Linq ...: -)


0 commentaires