2015-06-12 2 views
2

У меня есть переменная типа Dictionary<int, List<MyType>> где MyType - это класс с несколькими свойствами и методами. Я показываю только два свойства и никаких методов, поскольку они не имеют отношения к вопросу.Изменить значение свойства экземпляра класса внутри Словаря списков экземпляров класса

class MyType 
{ 
    private string property1; 
    private double property2; 

    public string Property1 
    { 
     get { return property1; } 
     set { property1 = value; } 
    } 

    public double Property2 
    { 
     get { return property2; } 
     set { property2 = value; } 
    } 

Я хотел бы перебрать словарь и найти все экземпляры класса, для которых свойство (скажем, например, свойство2) экземпляра класса имеет определенное значение.

Как только у меня есть это, я хотел бы изменить значение свойства и выполнить дополнительные вычисления.

Я искал, как это сделать, но не может найти ничего, что поможет. Я посмотрел на метод .ToLookup(), но я не уверен, как его использовать в этом контексте. Любая помощь будет оценена по достоинству.

+0

Действительно ли вам нужны ключевые значения словаря для любых ваших вычислений? – JNYRanger

ответ

2

Чтобы перебрать словарь, вы используете класс KeyValuePair<TKey,TValue>. Поскольку у вас есть список как ваше значение, вам нужно вложить петлю в итерацию словаря. Вот пример в предположении myDictionary имеет Dictionary<int, List<MyType>>:

foreach(var keypair in myDictionary) 
{ 
    foreach(MyClass m in keypair.Value.Where(v => v.Property1.Equals("something")) 
    { 
      //do whatever you want here with m being an object in the list of MyClass 
    } 
} 

LINQ Where оператор принимает лямбда, где каждый раз, когда лямбда будет возвращена истина, эти объекты станут частью итерации списка.

Если вы просто хотите IEnumerable<MyClass> из внутреннего списка и вы не заботитесь о ключах вы можете сделать это:

var iterableMyClass = myDictionary.SelectMany(kv => kv.Value) 
            .Where(v => v.Property2.Equals("something")); 

Теперь iterableMyClass является одной IEnumerable<MyClass> объект, который объединил все списки в пределах Словарь. Это связано с тем, что SelectMany используется для «сглаживания» нескольких коллекций. Операция Where также фильтрует возвращенный IEnumerable так же, как и в цикле foreach в моем первом примере.

Используя этот единственный IEnumerable, вы можете использовать простой foreach(MyClass m in iterableMyClass) для перебора всех объектов, которые соответствуют.

EDIT

За нашу дискуссию ниже, если вам нужно, чтобы получить количество или сказать, если IEnumerable содержит, по меньшей мере, один элемент, который вы можете сделать одно из следующих действий.

Чтобы получить количество матчей, вы можете просто позвонить .Count() на IEnumerable объекта, но если вы на самом деле не нужны предметы на все, что вы можете просто сделать это:

var count = myDictionary.SelectMany(kv => kv.Value).Count(v => v.Property2.Equals("something"); 

Чтобы получить логическое определение если есть хотя бы одно совпадение, но не нужны объекты, которые соответствуют:

bool atLeastOne = myDictionary.SelectMany(kv => kv.Value).Any(v => v.Property2.Equals("something"); 
+0

Я никогда не думал об этом, пока вы не упомянули об этом, но мне нравится IEnumerable. Будет ли переменная iterableMyClass быть списком всех экземпляров класса в словаре, которые соответствуют моим критериям в отношении Property2? – PBrenek

+0

@PBrenek Yup. Он по существу объединяет все списки в словаре в один IEnumerable, а затем фильтрует, поэтому только значения соответствия находятся внутри этого IEnumerable. Вы можете по существу рассматривать IEnumerable как List, который вы не можете редактировать. – JNYRanger

+0

Спасибо. Еще один пункт, который я хотел спросить. Есть ли способ получить количество элементов в IEnumerable? На самом деле мне нужно только знать, есть ли какие-либо записи или нет. Спасибо. Я думаю, iterableMyClass.Any() должен сделать трюк, нет? – PBrenek

3

Вы можете использовать два Foreach петли и метод расширения LINQ .Where:

using System.Linq; 

// ... 

foreach (KeyValuePair<int, List<MyType>> kv in dict) 
{ 
    foreach (MyType t in kv.Value.Where(v => v.Property2 == 2.0)) 
    { 
     // Use t for further calculations 
    } 
} 

Если вы хотите LINQ-менее решение, вы могли бы использовать, если заявление внутри внутреннего цикла:

foreach (KeyValuePair<int, List<MyType>> kv in dict) 
{ 
    foreach (MyType t in kv.Value) 
    { 
     if (t.Property2 != 2.0) continue; 
     // Use t for further calculations 
    } 
} 
Смежные вопросы