Rapide/moyen efficace d'obtenir l'indice de la valeur minimale dans la Liste des<T>?
Est-il possible de trouver la valeur minimale de l'indice de plus efficace/plus rapide que cela?
int minimumValueIndex = List.IndexOf(List.Min());
Assurez-vous. Écrire une boucle simple de trouver les deux valeurs: la valeur minimale dans la liste, et l'index dans lequel vous l'avez trouvé. Fait. Il est encore temps linéaire. Vous avez raison de croire que c'est votre goulot d'étranglement?
OriginalL'auteur Kamil | 2013-05-01
Vous devez vous connecter pour publier un commentaire.
Oui, vous pouvez supprimer la surcharge de
List.IndexOf()
par la construction d'une coutumeMin()
extension. (Vraiment,Enumerable.Min()
doit avoir une extension qui permet de sélectionner l' original élément clé au lieu de sélectionner une transformation. Cette surveillance est particulièrement douloureux dans des situations de ce genre.)C'est en quelque sorte un cas limite. Cependant, si
Min()
retournéTSource
au lieu deTResult
vous pouvez le faire avec de la vanille LINQ.Désolé pour la question idiote, mais que si je veux l'utiliser avec
List<int>
etList<double>
? J'ai besoin de deux extensions (certains surcharge), ou il y a un moyen de créer une extension qui fonctionne avec n'importe quel type de données numérique?Vous auriez besoin de deux surcharges, comme les opérateurs de comparaison ne peuvent pas être appliqués de façon générique sans certains hacks. (Modèles C++ pourrait gérer cela, mais pas de C# génériques.)
vous pourriez écrire un plus version générique. L'un contre l'
IEnumerable<T> where T : struct, IComparable
, et vous pouvez garder une trace de l'indice à la main.OriginalL'auteur cdhowie
Dans ma propre expérience, la LINQ méthodes d'agrégation tels que Tableau.Max() et de la Matrice.Min() sont généralement plus lents que d'un manuel pour la boucle. Ainsi, vous pouvez envisager quelque chose comme cela comme une approche alternative:
Vous pouvez toujours tester les vitesses de ces deux approches sur votre environnement à l'aide du Système.Diagnostics.Chronomètre.
J'ai mal lu la partie. Changé ma réponse en conséquence. Mais c'est toujours une seule boucle for.
OriginalL'auteur Prahlad Yeri
Il y a un problème avec la réponse posté par @cdhowie en ce qu'il suppose un
IList<T>
peut efficacement l'accès à un élément particulier par l'intermédiaire de son indexation. Alors qu'il vrai pour les tableaux etList[T]
, c'est à nono garantie (pour un exemple, une liste liée individuellement qui implémenteIlist<T>
).Si j'allais le faire dans un générique, Linqy façon, je ferais quelque chose comme:
Ou, sans doute plus propre, puisque nous débarrasser du superflu et de l'initialisation et étrangère comparer dans le corps de la boucle:
Vous pouvez également utiliser le stock de Linq
Aggregate()
surcharge, si c'est pas plus propre ou plus simple que la force brute de la méthode (probablement moins efficace, trop, à mon humble avis):OriginalL'auteur Nicholas Carey
Si possible, de garder trace de la valeur min/index que les valeurs sont placés dans la liste, de sorte que vous n'avez pas besoin d'une boucle sur une liste complète. Ensuite, si les nouvelles valeurs sont ajoutées à la liste, vérifiez la valeur min que vous avez enregistré, et de modifier la nouvelle valeur min que nécessaire.
De cours qui pourraient ne pas convenir à votre situation.
OriginalL'auteur Colton
J'ai amélioré @cdhowie de réponse un peu pour le rendre plus puissant. Si il y a plus d'un minimum d'éléments, alors cette méthode retourne la première.
Par exemple, nous avons une liste de
Person
.Person
a une propriétéLocation
, etLocation
se compose deX
etY
. Maintenant, nous voulons obtenir de la personne avec un minimum deY
, et si il y a plus d'une personne ont le même minimumY
, alors la personne avec un minimum deX
est ce que nous voulons. Dans ce cas, nous avons besoin de la fonction pour spécifierLocation
que la propriété que l'on souhaite comparer, et nous avons besoin de nous comparer à réaliser cette comparaison. Est-ce que mon explication logique?Non, je ne vois pas pourquoi ça ne peut pas être fait dans un
ICompare
.Aussi ce qui est
TOrder
?TOrder
est également un Type Générique, qui pourrait être n'importe quelle classe. Dans cette méthode,TOrder
est la classe à être comparés. Notez que même pour une classe, il pourrait y avoir de nombreuses façons de les comparer. Pour une instance deLocation
, parfois, on peut vouloir les comparer selonY
puisX
, mais parfois, on peut vouloir les comparer selonX
puisY
. C'est pourquoi je tiens à préciser comparer.OriginalL'auteur pengdlzn
Sûr. Il suffit d'écrire votre propre
Min
fonction, au lieu d'utiliser LINQ, qui conserve la trace de l'indice de l'actuelle valeur minimale. En faisant cela, vous pouvez éviter d'avoir à rechercher l'index de l'élément sur la base de sa valeur min.OriginalL'auteur Servy
Min de Calcul: Trouver le
Min
valeur dans une collection ne peut pas être fait plus vite que O(n) donc c'est peut-être pas de meilleur moyen que de cela, mais juste une autre dans le style de code.Trouver Étape: en fonction de votre problème, vous pouvez utiliser certains de structure de données (telles que l'arbre binaire, tas d'arbre, ...) de sorte que vous pouvez trouver l'index de plus en plus vite.
Oui. trouver l'index ne peut pas être une analyse complète, cependant, dans le pire des cas, il peut être O(n).
Le point est que le code de l'OP sera toujours ~2x plus longtemps que nécessaire. Si vous avez écrit votre propre fonction Min il pourrait revenir à l'index.
OriginalL'auteur Hossein Narimani Rad
Je suis paresseux et je voudrais donc utiliser:
C'est pas que c'est mal, mais pour obtenir la valeur minimale à partir de la liste, le plus que vous avez à faire est de scanner la liste de n éléments de n fois. Qui a un O(n) la complexité. Mais le tri est a un O( n log n ) la complexité, il est donc plus lent. Et enfin, si vous ne pouvez pas trier le tableau, alors que vous auriez à faire une copie d'un tableau et de sorte que, ce qui ajoute à la dépense.
OriginalL'auteur user3574895