2009-07-21 7 views
16

Je IQueryable<someClass> baseListLinq pour mettre à jour une collection avec des valeurs d'une autre collection?

et List<someOtherClass> someData

Ce que je veux faire est de mettre à jour les attributs de certains éléments baseList.

Pour chaque élément de someData, je souhaite trouver l'élément correspondant dans la liste de bas de page et mettre à jour une propriété de l'élément.

someOtherClass.someCode == baseList.myCode

je peux faire un certain type de se joindre à Linq et définir baseList.someData + = someOtherClass.DataIWantToConcantenate.

Je pourrais probablement le faire par itération, mais y a-t-il une façon élégante de Linq de le faire en quelques lignes de code?

Merci pour les conseils, ~ ck à San Diego

Répondre

19

Pour apparier des éléments dans les deux listes, vous pouvez utiliser un LINQ rejoindre:

var pairs = from d in someData 
      join b in baseList.AsEnumerable() 
       on d.someCode equals b.myCode 
      select new { b, d }; 

Cela vous donnera une énumération de chaque élément someData associé avec sa contrepartie en baseList. De là, vous pouvez concaténer dans une boucle:

foreach(var pair in pairs) 
    pair.b.SomeData += pair.d.DataIWantToConcantenate; 

Si vous avez vraiment voulu dire concaténation ensemble plutôt que +=, jetez un oeil à l'Union de LINQ, Intersection ou Sauf méthodes.

+0

Cela a fonctionné très bien pour moi. Je vous remercie! – Hcabnettek

+0

Merci beaucoup! – PramodChoudhari

12

LINQ est pour interrogation - pas pour la mise à jour. Cela signifie que ce sera bien d'utiliser LINQ pour trouver l'élément correspondant, mais pour la modification, devrait utiliser l'itération.

Certes, vous voudrez peut-être effectuer une requête appropriée pour obtenir baseList sous une forme efficace d'abord - par ex. un Dictionary<string, SomeClass> basé sur la propriété que vous utiliserez pour trouver l'article correspondant.

3

Vous pouvez convertir le IQueryable<SomeClass> en List<SomeClass>, utilisez la méthode ForEach en boucle sur elle et mettre à jour les éléments, puis reconvertir IQueryable:

List<SomeClass> convertedList = baseList.ToList(); 
convertedList.ForEach(sc => 
{ 
    SomeOtherClass oc = someData.First(obj => obj.SomeCode == sc.MyCode); 
    if (oc != null) 
    { 
     sc.SomeData += oc.DataIWantToConcatenate; 
    } 
}); 

baseList = convertedList.AsQueryable(); // back to IQueryable 

Mais il peut être plus efficace au cours de cette utilisation de non Constructions LINQ.

+0

serait-il à faire un croisement entre cette approche et l'approche acceptée, par exemple (à partir de d dans someData joindre b dans baseList.AsEnumerable() sur d.someCode est égal à b.myCode select new {b, d}). ToList.ForEach (a => { a.b.SomeData + = a.d.DataIWantToConcatenate; }); – stevenrcfox

0

Vous ne pouvez pas simplement trouver des objets dans une liste mais pas dans l'autre, car il existe deux types différents. Je suppose que vous comparez une propriété appelée OtherProperty qui est commune aux deux classes différentes et partage le même type. Dans ce cas, en utilisant rien requêtes LINQ:

// update those items that match by creating a new item with an 
// updated property 
var updated = 
    from d in data 
    join b in baseList on d.OtherProperty equals b.OtherProperty 
    select new MyType() 
    { 
     PropertyToUpdate = d.PropertyToUpdate, 
     OtherProperty = d.OtherProperty 
    }; 

// and now add to that all the items in baseList that weren't found in data 
var result = 
    (from b in baseList 
    where !updated.Select(x => x.OtherProperty).Contains(b.OtherProperty) 
    select b).Concat(updated); 
2

Comme mentionné précédemment, il devrait être une combinaison de boucle et LINQ

foreach (var someDataItem in someData) 
{ 
    someDataItem.PropertyToUpdate = (baseList.FirstOrDefault(baseListItem => baseListItem .key == someDataItem.key) ?? new SomeClass(){OtherProperty = "OptionalDefaultValue"}).OtherProperty; 
} 
Questions connexes