2009-07-21 14 views
16

tengo IQueryable<someClass> baseList¿Linq para actualizar una colección con valores de otra colección?

y List<someOtherClass> somedata

Lo que quiero hacer es atributos actualización en algunos artículos en baseList.

Para cada artículo en someData, quiero encontrar el artículo correspondiente en el punto de referencia y actualizar una propiedad del artículo.

someOtherClass.someCode == baseList.myCode

puedo hacer algún tipo de unirse con LINQ y establecer baseList.someData + = someOtherClass.DataIWantToConcantenate.

Probablemente podría hacer esto por iteración, pero ¿hay alguna forma elegante de Linq que pueda hacer esto en solo un par de líneas de código?

Gracias por cualquier consejo, ~ ck en San Diego

Respuesta

19

Para vincular los elementos en las dos listas se puede utilizar un LINQ Ingreso:

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

esto le dará una enumeración de cada elemento en someData emparejado con su contraparte en baseList. A partir de ahí, puede concatenar en un bucle:

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

Si realmente se quiere decir conjunto de concatenación en lugar de +=, echar un vistazo a Unión de LINQ, o Intersección Excepto métodos.

+0

Esto funcionó muy bien para mí. ¡Gracias! – Hcabnettek

+0

¡¡¡Muchísimas gracias !! – PramodChoudhari

12

LINQ es para consultar - no para la actualización. Eso significa que estará bien usar LINQ para encontrar el artículo correspondiente, pero para la modificación debe estar usando iteración.

Es cierto que es posible que desee realizar una consulta adecuada para obtener baseList en un formulario eficiente primero - p. a Dictionary<string, SomeClass> según la propiedad que utilizará para encontrar el artículo correspondiente.

3

Se puede convertir el IQueryable<SomeClass> en un List<SomeClass>, utilice el método ForEach para recorrer y actualizar los elementos, a continuación, convertir de nuevo a 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 

Pero puede ser más eficiente durante esta usando no Construcciones LINQ.

+0

sería trabajar para hacer un cruce entre este enfoque y el enfoque aceptado, por ejemplo (de d en someData join b en baseList.AsEnumerable() en d.someCode es igual a b.myCode seleccione nuevo {b, d}). ToList.ForEach (a => { a.b.SomeData + = a.d.DataIWantToConcatenate; }); – stevenrcfox

0

No puede simplemente encontrar los objetos que están en una lista pero no en la otra, porque son dos tipos diferentes. Asumiré que está comparando una propiedad llamada OtherProperty que es común a las dos clases diferentes, y comparte el mismo tipo. En ese caso, usando nada más que LINQ consulta:

// 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

Como se mencionó antes, debería ser una combinación de bucle y LINQ

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