Получение элементов из словаря по ключу - PullRequest
4 голосов
/ 20 сентября 2011

У меня есть такая структура:

static Dictionary<int, Dictionary<int, string>> tasks = 
    new Dictionary<int, Dictionary<int, string>>();

это выглядит так

[1]([8] => "str1")
[3]([8] => "str2")
[2]([6] => "str3")
[5]([6] => "str4")

Я хочу получить из этого списка все строки [8], что означает str1 + str2
Метод должен выглядеть следующим образом:

static List<string> getTasksByNum(int num){

}

Как мне получить к нему доступ?

Ответы [ 7 ]

5 голосов
/ 20 сентября 2011

С LINQ вы можете сделать что-то вроде:

return tasks.Values
            .Where(dict => dict.ContainsKey(8))
            .Select(dict => dict[8])
            .ToList();      

Хотя это и элегантно, шаблон TryGetValue обычно предпочтительнее двух операций поиска, которые он использует (сначала попытка ContainsKey, а затем использование индексатора для получения значения).

Если это проблема для вас, вы можете сделать что-то вроде (с подходящим вспомогательным методом):

return tasks.Values
            .Select(dict => dict.TryGetValueToTuple(8))
            .Where(tuple => tuple.Item1)
            .Select(tuple => tuple.Item2)
            .ToList();  
4 голосов
/ 20 сентября 2011

Просто переберите все значения первого уровня иерархии и используйте TryGetValue на втором уровне:

var result = new List<string>();
foreach(var inner in tasks.Values)
{
    string tmp;
    if(inner.TryGetValue(yourKey, out tmp)
        result.Add(tmp);
}

Это решение имеет большое преимущество перед всеми другими представленными решениями: Он фактически использует словари второго уровня иерархии в качестве словаря, то есть часть внутри цикла foreach - это O (1) вместо O (n), как и во всех других решениях.

3 голосов
/ 20 сентября 2011

Проверьте эту функцию:

   tasks.
      Where(task => task.Value.ContainsKey(8)).
      Select(task => task.Value[8]);
2 голосов
/ 20 сентября 2011

Решение Даниэля, вероятно, лучше, так как его легче понять. Но можно использовать TryGetValue и в подходе linq:

return tasks.Values
    .Select(dictionary => {
        string task;
        var success = dictionary.TryGetValue(yourKey, out task);
        return new { success, task };
    })
    .Where(t => t.success)
    .Select(t => t.task)
    .ToList();
1 голос
/ 20 сентября 2011

Вы строите задания?
И если я угадаю правильно, это задачи [task_id] ([cpu] => «имя_задачи»);
Я бы посоветовал вам также собрать cpu_tasks [cpu] ([task_id] => "task_name);

static Dictionary<int, Dictionary<int, string>> cpu_tasks

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

0 голосов
/ 20 сентября 2011
Dictionary<int, Dictionary<int, string>> tasks = new Dictionary<int, Dictionary<int, string>>();
var result = string.Empty;

//more human-readable version
var searchValue = 8;
foreach (var task in tasks)
{
     if (task.Value.ContainsKey(searchValue))
         result += task.Value[searchValue];
}

//one-line version
result = tasks.ToList().Aggregate(string.Empty, (a, kvp) => a += kvp.Value.ContainsKey(searchValue) ? kvp.Value[searchValue] : string.Empty);
0 голосов
/ 20 сентября 2011
Dictionary<int, Dictionary<int, string>> tasks = new Dictionary<int, Dictionary<int, string>>();

List<string> strings = new List<string>();
foreach(var dict in tasks.Values)
{
  if(dict.ContainsKey(8))
      strings.Add(dict[8]);
}
...