Linq для обновления свойства A. свойства с соответствующим свойством B., где A. Ключ == B. Ключ

#c# #linq

Вопрос:

У меня есть класс:

 public class Class1
{
    public int Id { get; set; }
    public double MyDouble { get; set; }
    public string SomeOtherValue { get; set; }
}
 

И у меня есть два словаря<int, Class1>:

 Dictionary<int, Class1> blankValues = new Dictionary<int, Class1>();
blankValues.Add(1, new Class1() { Id = 1, MyDouble = 0 });
blankValues.Add(2, new Class1() { Id = 2, MyDouble = 0 });
blankValues.Add(3, new Class1() { Id = 3, MyDouble = 0 });

Dictionary<int, Class1> currentValues = new Dictionary<int, Class1>();
currentValues.Add(2, new Class1() { Id = 2, MyDouble = 3.1415927 });
 

Я хочу просмотреть словарь blankValue и для каждого элемента в currentValue, где blankValue.Ценность.Идентификатор = = Текущее значение.Ценность.Идентификатор, который я хочу установить, имеет значение Blank.Ценность.myDouble = текущее значение.Ценность.Моя двойка.

Конечный результат в словаре пустых значений приведет к:

 Class1() { Id = 1, MyDouble = 0 });
Class1() { Id = 2, MyDouble = 3.1414927 });
Class1() { Id = 3, MyDouble = 0 });
 

Это похоже на то, что мне нужен вложенный Linq. Я бы поместил здесь то, что я пробовал, но каждая моя попытка даже близко не подходит к компиляции. Как обычно выглядит такой Linq?

редактировать — Я должен добавить, что класс имеет более двух значений. Я хочу сохранить все значения свойств в словаре пустых значений, за исключением одного или двух.

Комментарии:

1. Приведите, пожалуйста, пример для вашего последнего требования

2. Совпадает ли ключ словаря со Value.ID свойством, которое вы упомянули в своем желаемом поведении? Есть ли причина не просто писать простой код с явным циклом?

Ответ №1:

GroupJoin документы: Если в данном элементе нет коррелированных элементов inner outer , последовательность совпадений для этого элемента будет пустой, но все равно будет отображаться в результатах.

Я предполагаю, что идентификаторы уникальны в каждом словаре.

 blankValues = blankValues.GroupJoin(
    currentValues,
    pair => pair.Value.Id,
    pair => pair.Value.Id,
    // Select rather blank values member or current values member
    (blankValue, matches) => matches.Any() ? matches.First() : blankValue))
.ToDictionary(x => x.Id, x => x)

 

Комментарии:

1. С ума сошел. Это делает свое дело. Теперь, чтобы действительно понять магию, которую вы цитируете!

2. @Eric Снайдер это на самом деле не сложно, потому что то, что вы ищете, в основном blankValues left join currentValues , если бы мы делали это на SQL. Но в Linq этого нет .LeftJoin … Поэтому я погуглил, как это имитировать.

Ответ №2:

Я думаю, вы хотите проверить по словарю.Ключ не dictionary.Value.Id:

 foreach (var (key, value) in currentValues )
{
    if (blankValues.ContainsKey(key))
    {
        blankValues[key] = value;
        continue;
    }
    //remove line below if you don't need to add missing values in first list
    blankValues.Add(key, value);
}
 

Или, если вам действительно нужно проверить по идентификатору, это будет выглядеть примерно так:

 foreach (var (key, value) in currentValues)
{
    var blanks = blankValues
                 .Where(x => x.Value.Id == value.Id)
                 .ToList();
    foreach (var blank in blanks)
    {
        blankValues[blank.Key] = value;
    }
}