2011-05-03 4 views
4

Le contexte est que j'ai un ensemble de valeurs en mémoire cache qui étaient chères à extraire, et un autre ensemble de données associées qui est peu coûteux à récupérer et ne peut pas être mis en cache (règle métier) . Je l'ai tout travail mais je me demandais si quelqu'un pouvait penser à une façon moins coûteuse de faire ce genre de mise à jour ...comparer et mettre à jour deux listes dans C#

foreach (var nonCachedItem in searchItemsNonCached) 
    { 
     foreach (var cachedItem in searchItemsCached) 
     { 
      if (cachedItem.ID == nonCachedItem.ID) 
       nonCachedItem.Description = cachedItem.Description; 
     } 
    } 

il est fondamentalement juste de faire correspondre les informations mises en cache avec les informations que je juste obtenu. Tout fonctionne et la charge est presque négligeable mais je suis un peu un aspirant pour l'efficacité.

EDIT: dans ce qui précède, searchItemsNonCached et searchItemsCached sont deux listes de SearchItem où Searchitem est un objet sur mesure.

+3

Quels sont les types de searchItemsNonCached et de searchItemCached? Ont-ils une recherche plus rapide que O (n)? Sont-ils triés? –

+0

Une autre possibilité que vous pouvez utiliser est Paralléliser la recherche –

Répondre

2

Chargez un Dictionary avec les éléments mis en cache, puis parcourez chaque élément non mis en cache à la recherche d'une correspondance dans le dictionnaire. C'est O(n) par opposition à la boucle imbriquée qui est O(n^2).

var cachedDictionary = new Dictionary<int, YourType>(); 
foreach (var item in searchItemsCached) 
{ 
    cachedDictionary.Add(item.ID, item); 
} 
foreach (var item in searchItemsNonCached) 
{ 
    YourType match; 
    if (cachedDictionary.TryGetValue(out match)) 
    { 
    item.Description = match.Description; 
    } 
} 

Si vous pouvez envisager d'utiliser un Dictionary pour les éléments mis en cache depuis le début (au lieu d'un List), vous pouvez alors éviter l'étape de la charger avant de trouver des correspondances.

5

Stockez vos éléments mis en cache dans un dictionnaire. Maintenant vous pouvez mettre à jour seulement si la clé existe.

-1

Une autre approche est que vous pouvez écrire une expression linq et joindre les deux listes sur ID, et créer de nouveaux objets de même type avec des valeurs mises à jour.

ex

from nc in searchItemsNonCached 
join c in searchItemCached on nc.ID equals c.ID 
select new (same type) // and assign the desc from c.Description 
0

Qu'est-ce que vous essayez de faire est essentiellement une jointure (au sens de la base de données), en particulier une équi-jointure. Vous pouvez consulter this section of a Wikipedia article sur les algorithmes de jointure. Le code que vous avez indiqué ci-dessus est une jointure en boucle imbriquée, et la suggestion d'adymitruk est une jointure de hachage, mais comme l'a commenté Lou Franco, la meilleure approche dépend probablement du type de commande ou de structure (le cas échéant) de vos collections. searchItemCached Si searchItemCached est juste une liste non ordonnée, alors hash join est probablement votre meilleur pari - il suffit de construire un dictionnaire d'une collection ou l'autre avec l'ID comme clé, puis bouclez l'autre collection en recherchant les éléments correspondants du dictionnaire. Si searchItemCached est déjà un dictionnaire clé par ID, alors une jointure de hachage est définitivement votre meilleur pari. Si searchItemCached et searchItemsNonCached sont tous les deux triés par ID, alors un sort-merge join est probablement le chemin à parcourir.

+0

la jointure de hachage utilise beaucoup de mémoire, il devrait être conscient de cela, mais l'ordre est la somme des deux comptes d'entrée. O (input1.count + input2.count). –

+0

@Gabriel Bon point, il y a un compromis espace-temps ici. Bien que 'searchItemCached' soit déjà un dictionnaire, aucun espace supplémentaire n'est nécessaire. – Aaron

+0

Désolé aurait dû mentionner que, ils sont les deux listes d'objets sur mesure –