Linq для обновления коллекции со значениями из другой коллекции?
У меня IQueryable<someClass>
baseList
и List<someOtherClass>
someDatap >
То, что я хочу сделать, это обновить атрибуты в некоторых элементах в baseList.
Для каждого элемента в someData я хочу найти соответствующий элемент в baselist и обновить свойство элемента.
someOtherClass.someCode == baseList.myCode
Могу ли я сделать некоторый тип соединения с Linq и установить baseList.someData + = someOtherClass.DataIWantToConcantenate.
Я мог бы, вероятно, сделать это с помощью итерации, но есть ли причудливый способ Linq, я могу сделать это всего за пару строк кода?
Спасибо за любые советы,
~ ck в Сан-Диего
Ответы
Ответ 1
Для объединения элементов в два списка вы можете использовать LINQ join:
var pairs = from d in someData
join b in baseList.AsEnumerable()
on d.someCode equals b.myCode
select new { b, d };
Это даст вам перечисление каждого элемента в someData
в паре с его копией в baseList
. Оттуда вы можете конкатенатироваться в цикле:
foreach(var pair in pairs)
pair.b.SomeData += pair.d.DataIWantToConcantenate;
Если вы действительно имели в виду установку конкатенации, а не +=
, взгляните на методы LINQ Union, Intersect или Except.
Ответ 2
LINQ предназначен для запросов - не для обновления. Это означает, что будет удобно использовать LINQ для поиска соответствующего элемента, но для модификации вы должны использовать итерацию.
По общему признанию, вы можете выполнить какой-то соответствующий запрос, чтобы сначала получить baseList
в эффективную форму - например, a Dictionary<string, SomeClass>
на основе свойства, которое вы будете использовать, чтобы найти соответствующий элемент.
Ответ 3
Вы можете преобразовать IQueryable<SomeClass>
в List<SomeClass>
, использовать метод ForEach
, чтобы перебрать его и обновить элементы, а затем преобразовать обратно в 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
Но это может быть более эффективным при использовании конструкторов, отличных от LINQ.
Ответ 4
Как упоминалось ранее, это должна быть комбинация цикла и LINQ
foreach (var someDataItem in someData)
{
someDataItem.PropertyToUpdate = (baseList.FirstOrDefault(baseListItem => baseListItem .key == someDataItem.key) ?? new SomeClass(){OtherProperty = "OptionalDefaultValue"}).OtherProperty;
}
Ответ 5
Вы не можете просто найти объекты, которые находятся в одном списке, но не другие, потому что они представляют собой два разных типа. Я предполагаю, что вы сравниваете свойство под названием OtherProperty, которое является общим для двух разных классов, и имеет один и тот же тип. В этом случае, используя только запросы 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);