2012-02-27 2 views
6

Итак, вы можете получить одно значение на dictionary[key] или все значения на dictionary.Values.C# get value subset from dictionary by keylist

То, что я ищу, это способ получить все значения для данного ключа набора следующим образом:

List<string> keys; 
Dictionary<string, object> dictionary; 

List<object> valuesForKeys = GetValuesFromDictionaryUsingKeys(dictionary, keys); 

с

private List<object> GetValuesFromDictionaryUsingKeys(Dictionary<string, object> dictionary, List<string> keys) 
{ 
    //your code here 
} 

Конечно, я мог бы итерацию вручную по KeyList и использования dictionary[key] и снова добавить все значения в список, но я хотел бы использовать более элегантный способ (например, Linq).

Спасибо.

ответ

10

Пробег: keys.Where(k => dictionary.ContainsKey(k)).Select(k => dictionary[k]).

+2

Sh * т я должен узнать некоторые LINQ: D – Shai

+2

Это _always_ время, чтобы узнать some linq: D – Rawling

+0

Спасибо, именно то, что я искал. – christoph

2
private List<object> GetValuesFromDictionaryUsingKeys(Dictionary<string, object> dictionary, List<string> keys) 
{ 
    List<object> nList = new List<object>(); 

    foreach (string sKey in keys) 
     if (dictionary.ContainsKey(sKey)) 
      nList.Add(dictionary[sKey]); 

    return nList;   
} 
+1

Обратите внимание, что отсутствие недостатка Linq в стороне, это шаг через словарь и поиск в списке - вы бы _much_ лучше по производительности, перешагнув список и выполнив поиск в словаре. – Rawling

+0

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

+0

@ AvnerShahar-Kashtan спасибо за ваш комментарий * и * -1 – Shai

6

Зачем писать функцию, если у вас есть общий метод расширения для повседневного использования?

public static IEnumerable<V> GetValues<K, V>(this IDictionary<K, V> dict, IEnumerable<K> keys) 
{ 
    return keys.Select((x) => dict[x]); 
} 

EDIT: Чем вы можете написать:

var valuesForKeys = dictionary.GetValues(keys).ToList(); 
+0

Также вы можете использовать ContainsKey() как Rawling, если вы не уверены, что существуют ключи. – watbywbarif

+0

Ницца. Не знал общих методов расширения. Благодаря! – christoph

+0

Ницца, +1. Удалите 'ToList()' и просто заставьте его возвратить 'IEnumerable ', и это будет еще приятнее и LINQy. – Rawling

2

Try:

List<object> valuesForKeys = keys.Intersect(dictionary.Keys) 
            .Select(k => dictionary[k]) 
            .ToList(); 

или по запросу:

private List<object> GetValuesFromDictionaryUsingKeys(Dictionary<string, object> dictionary, List<string> keys) 
{ 
    // My code here 
    return keys.Intersect(dictionary.Keys) 
       .Select(k => dictionary[k]) 
       .ToList();  
} 

Использование .Intersect, чтобы удалить ключи, не присутствующие в словаре, это быстрее, чем .Where(k => dictionary.ContainsKey(k)).

Удалить инструкцию .Intersect, чтобы разрешить создание исключения для ключа, не найденного в словаре.

+0

Как я понимаю, Intersect использует сопоставитель по умолчанию, который может быть не таким, каким вы хотите.Например, если вы инициализируете свой словарь следующим образом: новый словарь (StringComparer.OrdinalIgnoreCase), это не будет уважать компаратора. – BlakeH

0

Ролинг ответ работает безупречно, но если вы знаете заранее ключи существуют по словарю, это может быть более ясным и эффективным: keys.Select(k => dictionary[k])