Подтвердить что ты не робот

Linq для обновления коллекции со значениями из другой коллекции?

У меня IQueryable<someClass> baseList

и List<someOtherClass> someData​​p >

То, что я хочу сделать, это обновить атрибуты в некоторых элементах в baseList.

Для каждого элемента в someData я хочу найти соответствующий элемент в baselist и обновить свойство элемента.

someOtherClass.someCode == baseList.myCode

Могу ли я сделать некоторый тип соединения с Linq и установить baseList.someData + = someOtherClass.DataIWantToConcantenate.

Я мог бы, вероятно, сделать это с помощью итерации, но есть ли причудливый способ Linq, я могу сделать это всего за пару строк кода?

Спасибо за любые советы, ~ ck в Сан-Диего

4b9b3361

Ответ 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);