J'ai deux collections Je ne veux pas utiliser de boucle ou quelque chose parce que je pense qu'il devrait y avoir beaucoup de meilleure façon de le faire. P> i Je cherche un moyen plus efficace de comparer ces collections et d'obtenir des résultats: p> type de type AT ID de propriété. P> Il y avait une réponse, qui est déjà supprimée en disant
Ce que je veux dire en disant efficacement: moins de code, moins de mécanique et des cas plus lisibles p> Alors, pensant ainsi quel est les cas que j'ai? P> Quel serait moins de code, moins de mécanique et des cas plus lisibles? p> p>
8 Réponses :
Vous pouvez utiliser mais cela n'a aucun avantage de performance sur la solution performant dans le sens de la performance, une meilleure approche serait de ne pas utiliser de liste sauf code>:
foreach code>. Ça a l'air plus propre.
Aussi, soyez conscient du fait que vous devez implémenter iéquatif
list
Mais c'est en essence une boucle
@LANDONCZ: Je sais. Je pense qu'il est impossible de ne pas utiliser de boucle.
Je suis d'accord, techniquement, vous devez utiliser une boucle à moins que vous ne fassiez à une récursion folle (alors vous allez avoir quelque chose d'inacceptable et risque de souffler la pile).
C'est sûr que j'allais dire cela aussi, mais décidé contre cela pour la brièveté.
@Daniel Hilgarth Première chose que j'ai essayé la méthode .Except (), mais que j'ai réalisé que je dois mettre en œuvre Iequatable
Vous pouvez le faire comme ceci:
// 1) List of cars in newCars and not in currentCars var newButNotCurrentCars = newCars.Except(currentCars); // 2) List of cars in currentCars and not in newCars var currentButNotNewCars = currentCars.Except(newCars);
+1, Linq est probablement un moyen simple, en particulier avec Sauf () .
+1 Mais il n'y a aucune garantie que, sauf exercer une exécution A pour chacun puisqu'il utilisera probablement iEnumerable et pour acheter de toutes les manières.
Il a dit qu'il ne voulait pas une boucle de Foreach, cela pourrait être à cause de la lisibilité, il n'a pas précisé. Je vais aller à côté de la question collante des performances et donne le code le plus lisible et le plus maintenu.
Je voudrais remplacer le égal code> d'un
voiture code> pour comparer par ID, puis vous pouvez utiliser la méthode
ienumerable.except code> méthode d'extension. Si vous ne pouvez pas remplacer le
égale code> Vous pouvez créer votre propre
iéqualitycomparer
class CarComparer : IEqualityComparer<Car>
{
public bool Equals(Car x, Car y)
{
return x != null && y != null && x.Id == y.Id;
}
public int GetHashCode(Car obj)
{
return obj == null ? 0 : obj.Id;
}
}
Je pense que c'est la seule façon de le faire sans boucle à travers chaque article de la manière.
@LANDONCZ: Je ne vois pas comment cela évite une boucle. Il suggère également d'utiliser le à l'exception de la méthode d'extension code>, bien qu'il l'a mal orthographié.
Désolé, je pensais qu'il remplace toute la liste comme ça, d'oh, devinez que vous ne pouvez pas ajouter de code aux réponses ...
Vous pouvez utiliser LINQ ...
List<Car> currentCars = new List<Car>(); List<Car> newCars = new List<Car>(); List<Car> currentButNotNew = currentCars.Where(c => !newCars.Contains(c)).ToList(); List<Car> newButNotCurrent = newCars.Where(c => !currentCars.Contains(c)).ToList();
Si vous commencez avec eux dans Hashset code> s Vous pouvez utiliser le
sauf code> méthode.
HashSet<Car> currentCars = GetCurrentCars();
HashSet<Car> newCars = GetNewCars();
currentCars.Except(newCars);
newCars.Except(currentCars);
+1 pour hashset. Bien qu'il fonctionnera plus rapidement, cela consommera plus de mémoire et le coût initial de remplissage du hashset sera plus élevé. Vous ne devez utiliser que HASHSET si vous envisagez d'utiliser la même collection plusieurs fois.
Très vrai. Le compromis est presque toujours la taille de la vitesse, cependant.
Hashset a-t-il une spéciale, sauf que ce n'est pas la méthode d'extension LINQ? Je pense que vous vouliez dire sauf, qui mutait en place.
Si vous recherchez une efficacité, implémentez Icomarable sur les voitures (triant sur votre identifiant unique) et utilisez une tige de tri. Vous pouvez ensuite parcourir vos collections ensemble et évaluer vos chèques dans O (N). Ceci est bien sûr fourni avec un coût supplémentaire pour la liste des inserts pour maintenir la nature triée. P>
Vous pouvez copier la liste plus petite dans une collection basée sur une table de hachage, comme HASHSET ou Dictionnaire, puis itérer sur la deuxième liste et vérifier si l'élément existe dans la table de hachage. P>
Cela réduira le temps de O (n ^ 2) dans la naïve pourche à l'intérieur de l'affaire O (n). P>
C'est le meilleur que vous puissiez faire sans en savoir plus sur les listes (vous pourrez peut-être faire un petit em> mieux si les listes sont triées par exemple, mais, puisque vous devez "toucher" Chaque voiture au moins une fois pour vérifier si c'est sur la nouvelle liste de voitures, vous ne pouvez jamais faire mieux que O (n)) P>
Si une comparaison de la propriété ID vous suffira de dire si une voiture est égale à une autre, afin d'éviter une sorte de boucle, vous pouvez remplacer la liste avec votre propre classe qui garde la trace des articles et utilise le IéqualityComparer Code> sur toute la collection, comme celui-ci:
class CarComparer : IList<Car>, IEquatable<CarComparer>
{
public bool Equals(CarComparer other)
{
return object.Equals(GetHashCode(),other.GetHashCode());
}
public override int GetHashCode()
{
return _runningHash;
}
public void Insert(int index, Car item)
{
// Update _runningHash here
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
// Update _runningHash here
throw new NotImplementedException();
}
// More IList<Car> Overrides ....
}
Les opérations que vous décrivez sont des "différences définies". Si vous devez calculer beaucoup de différences de réglage, ou sur des ensembles volumineux, vous ne devez pas utiliser la liste en premier lieu. Vous devez utiliser HASHSET , une structure de données spécifiquement optimisée pour calculer ces types de différences.
@ Sciences lippert dans mon cas, ce sont de très petits ensembles (1-3 articles), donc je pense qu'il n'y a pas besoin de hashset.