2010-06-08 2 views
1

Что было бы лучшим способом поиска значения в словаре. Например, я хотел бы искать измененные объекты, будет ли доступ ко всей коллекции единственным способом сделать это?Как найти значения в словаре

C#, .net 2.0

class RecA 
{ 
public bool modified {get;set:} 
public string txt {get;set;} 
} 

class RecA_Dic : Dictionary<int,Rec_A> 
{ 

    public bool GetItemByKey(int key,out obj) 
    { 
    return this.TryGetValue(key, out obj); 
    } 

    public List<Rec_A> getModifiedItems() 
    { 
    List<Rec_A> li = new List<Rec_A>(); 
    for(int i=0;i<this.count;i++) 
     if (((Rec_A)this[i]).modified == true) 
     li.Add((Rec_A)this[i]); 
    return li; 
    } 

} 
+0

Словарь <> не имеет индексатора [int], если его тип ключа не является int. – Humberto

+1

... и в этом случае, [int] не делает, что вы думаете! – n8wrl

+0

@Humberto: тип ключа * есть * int в примере. – Randolpho

ответ

7

Учитывая ограничения (.NET 2.0), вы почти достигли цели. IEnumerable<Rec_A> плюс yield return является лучшей альтернативой, IMO:

public IEnumerable<Rec_A> getModifiedItems() 
{ 
    foreach (Rec_A rec in this.Values) 
    { 
    if (rec.modified) 
     yield return rec; 
    } 
} 
+0

Мне нравится этот ответ лучше всего. +1 – Randolpho

+5

Это очень чистое, но одно предупреждение: если по какой-то причине идентификация измененных записей означает, что он должен удалить их из словаря, это перечисление будет выброшено. – n8wrl

+0

@ n8wrl: отличная точка. – Randolpho

0

Да. Либо вы должны проверить каждое значение, либо вам придется отслеживать изменения в другой структуре данных, например список измененных объектов. (Вы можете скрыть это в своей специализированной реализации словаря.)

2

Да, словарь имеет быстрый поиск ключа. Если вы хотите найти что-либо в значении, вам нужно пройти всю коллекцию.

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

1

Поиск через весь словарь, безусловно, самый простой способ сделать это, хотя foreach петля будет чище:

foreach (KeyValuePair<int, Rec_A> kvp in d) 
{ 
    // Check kvp.Value 
} 

Если вы хотите поиски чтобы быть быстрее, вы могли бы добавить свои измененные объекты в отдельный список в момент их изменения. Тем не менее, это замедлит изменения, так что здесь есть компромисс.

1

Основной ответ на ваш вопрос: да, вы должны перебирать значения, чтобы найти измененные.

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

1) Прежде всего, ваш код будет работать даже на работу. Это потому, что вы обрабатываете ключи в Dictionary как индексы в List или Array. Ваш цикл for начинает i в 0 и увеличивает его до Count (это номер KeyValuePair s кстати). Но что, если у меня нет значения в Dictionary с ключом, равным 0? В общем, вы получите исключение что-то вроде этого:

RecA_Dic myD = new RecA_Dic(); 
myD.Add(10,new Rec_A()); 
myD.getModifiedItems(); //throws KeyNotFoundException 

Теперь, если вы добавляете значения в Dictionary с индексом нулевой основе, то, что возникает вопрос о том, почему использовать Dictionary когда List будет делать?

2) Вам не нужно делать отливки на this[i]. Поскольку вы сказали Dictionary, что он будет содержать значения Rec_A, он вернет значения как Rec_A. Это красота дженериков.

3) Вам не нужно сравнивать modified с true в заявлении if.При работе с bool переменными обычно считается хороший этикет, чтобы не сравнивать их с true или false. На боковой ноте вы можете рассмотреть возможность переименования modified в IsModified. Это лучше согласуется со многими стандартными соглашениями об именах и делает код более удобочитаемым.

4) По возможности попытайтесь использовать foreach вместо for. В этом случае foreach бы на самом деле решить эту проблему, я уже упоминал в 1.

5) Как Умберто упоминался вы можете рассмотреть вопрос о возвращении IEnumerable и используя yield return. Это дает вам преимущество отсроченного исполнения.

6) И наконец, почему вы унаследовали от Dictionary? Основываясь на вашем коде, я бы предположил, что вы могли бы просто создать Dictionary и сделать свой getModified метод static и сделать его в качестве параметра Dictionary (или , если это все, что вам действительно нужно).

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

Смежные вопросы