Fondamentalement, comment puis-je le faire pour que je puisse faire quelque chose de similaire à: CurrentCollection.Contains(...)
, sauf en comparant si la propriété de l'élément est déjà dans la collection?
public class Foo
{
public Int32 bar;
}
ICollection<Foo> CurrentCollection;
ICollection<Foo> DownloadedItems;
//LINQ: Add any downloaded items where the bar Foo.bar is not already in the collection?
Vous commencez par trouver quels éléments ne sont pas déjà dans la collection:
var newItems = DownloadedItems.Where(x => !CurrentCollection.Any(y => x.bar == y.bar));
Et puis ajoutez-les simplement:
foreach(var item in newItems)
{
CurrentCollection.Add(item);
}
Notez que la première opération peut avoir une complexité quadratique si la taille de DownloadedItems
est proche de celle de CurrentCollection
. Si cela pose problème (mesurez d'abord!), Vous pouvez utiliser un HashSet
pour ramener la complexité à linéaire:
// collect all existing values of the property bar
var existingValues = new HashSet<Foo>(from x in CurrentCollection select x.bar);
// pick items that have a property bar that doesn't exist yet
var newItems = DownloadedItems.Where(x => !existingValues.Contains(x.bar));
// Add them
foreach(var item in newItems)
{
CurrentCollection.Add(item);
}
Utilisation de la méthode R.Martinho Fernandes et conversion en 1 ligne:
CurrentCollection.AddRange(DownloadedItems.Where(x => !CurrentCollection.Any(y => y.bar== x.bar)));
Vous pouvez utiliser Enumerable.Except :
Il comparera les deux listes et renverra les éléments qui apparaissent uniquement dans la première liste.
CurrentCollection.AddRange(DownloadedItems.Except(CurrentCollection));
Vous pouvez appeler la méthode Any
et transmettre une valeur à comparer à n'importe quelle propriété du type d'objet de la collection.
if (!CurrentCollection.Any(f => f.bar == someValue))
{
// add item
}
une solution plus complète pourrait être:
DownloadedItems.Where(d => !CurrentCollection.Any(c => c.bar == d.bar)).ToList()
.ForEach(f => CurrentCollection.Add(f));
Ou en utilisant All
CurrentCollection
.AddRange(DownloadedItems.Where(x => CurrentCollection.All(y => y.bar != x.bar)));
Une des choses que vous pouvez faire est de penser que le moyen le plus simple est de créer un HashSet au lieu d’une Liste. Par défaut, le HashSet n’ajoute pas de valeurs redondantes.
var newItems = DownloadedItems.Where(i => !CurrentCollection.Any(c => c.Attr == i.Attr));
Vous pouvez le faire comme ceci:
CurrentCollection.Any(x => x.bar == yourGivenValue)