#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;
}
}