迭代整个字典以获得特定的值和关键

时间:2015-01-17 19:50:31

标签: c# loops dictionary lambda

我目前正在打印特定键的值,如下所示:

        var myValue = dic1.FirstOrDefault(x => x.Key == "John").Value;
        Console.WriteLine("John in dictionary: " + myValue);

值是约翰在这本词典中多少次的数字。现在我想为整本字典这样做。有任何想法吗?我想过要做到这样:

            var dic1Dic2 = dic1.Zip(dic2, (d, z) => new { Dic1= d, Dic2 = z });
            foreach (var dz in dic1Dic2)
            {
                Console.WriteLine(dz.Dic1);
                Console.WriteLine(dz.Dic2);
            }

但在这种情况下,问题是如果其中一个列表较小,我就不会得到值。地狱,如果一个人得到100个字而且没有,如果没有打印。

我想计算就像在dic1中我说得到键=四和值= 4,在dic2中我得到四和值= 2(例如,它也可能是4,无关紧要),而我想要倍增它们,或分裂或其他什么。在最基本的第一个代码示例中,当我只使用特定键值时,我这样做:

        var divideJohn = (myValue1 / myValue);

和myValue1来自:

var myValue1 = dic2.FirstOrDefault(x => x.Key == "John").Value;

那么任何想法如何从字典中的所有内容中获取这些值?

@edit 是的,澄清一下,我有很多词典,我希望他们每个人的价值都能得到一些数学。对于一个制作foreach循环的字典就足够了:

       foreach (string item in dic1.Keys)
        {
            var dif = dic1.FirstOrDefault(x => x.Key == item).Value;                                  
        }

但重点是从不同的词典中获取它们并能够在数学中使用它们。

1 个答案:

答案 0 :(得分:0)

不幸的是,你的问题并不是很清楚你想要做什么。您的问题陈述中遗漏了许多细节,这些细节将明确指出所需的实际行为。

那就是说,听起来你正在尝试合并你的词典。一个非常简单的版本可能是:

Dictionary<string, int> MergeSum(
    Dictionary<string, int> dict1, Dictionary<string, int> dict2)
{
    Dictionary<string, int> merged = new Dictionary<string, int>(dict1.Count);

    foreach (var kvp in dict1)
    {
        merged.Add(kvp.Key, kvp.Value + dict2[kvp.Key]);
    }
}

请注意,上面隐含的假设是两个词典都包含完全相同的键。不做出这种假设的替代方案可能如下所示:

Dictionary<string, int> MergeSum(
    Dictionary<string, int> dict1, Dictionary<string, int> dict2)
{
    Dictionary<string, int> merged = new Dictionary<string, int>(dict1.Count);

    foreach (var kvp in dict1)
    {
        int value;

        dict2.TryGetValue(kvp.Key, out value);
        merged.Add(kvp.Key, kvp.Value + value);
    }

    foreach (var kvp in dict2)
    {
        int value;

        if (!dict1.TryGetValue(kvp.Key, out value))
        {
            merged.Add(kvp.Key, kvp.Value);
        }
    }
}

此处,value如果在调用TryGetValue()时字典中不存在,则会设置为0.

在您的问题中,您似乎表明您可能有两个以上的词典要合并。在这种情况下,您可以将字典数组(或其他集合...数组作为输入作为输入,仅用于说明目的):

Dictionary<string, int> MergeSum(Dictionary<string, int>[] dictionaries)
{
    Dictionary<string, int> merged = new Dictionary<string, int>();

    foreach (Dictionary<string, int> dict in dictionaries)
    {
        foreach (var kvp in dict)
        {
            int value;

            merged.TryGetValue(kvp.Key, out value);
            merged[kvp.Key] = kvp.Value + value;
        }
    }
}

您可能希望以通用方式执行上述任何操作。这可能看起来像这样:

Dictionary<string, int> Merge(
    Dictionary<string, int>[] dictionaries, Func<int, int, int> mergeFunction)
{
    Dictionary<string, int> merged = new Dictionary<string, int>();

    foreach (Dictionary<string, int> dict in dictionaries)
    {
        foreach (var kvp in dict)
        {
            int value;

            merged.TryGetValue(kvp.Key, out value);
            merged[kvp.Key] = mergeFunction(value, kvp.Value);
        }
    }
}

您可以这样调用上面的内容:

result = Merge(dictionaries, (i1, i2) => i1 + i2);

有些操作比其他操作更有问题。例如,如果您正在使用乘法,那么由于代码总是从空的初始字典聚合,因此聚合操作结果将始终为0.您可以通过特殊包装第一个字典来解决此问题:

Dictionary<string, int> Merge(
    Dictionary<string, int>[] dictionaries, Func<int, int, int> mergeFunction)
{
    Dictionary<string, int> merged = new Dictionary<string, int>(dictionaries.First());

    foreach (Dictionary<string, int> dict in dictionaries.Skip(1))
    {
        foreach (var kvp in dict)
        {
            int value;

            merged.TryGetValue(kvp.Key, out value);
            merged[kvp.Key] = mergeFunction(value, kvp.Value);
        }
    }
}

这将使用集合中的第一个字典初始化merged字典,然后在执行实际聚合循环时跳过该字典。但请注意,即使在那里,在处理每个字典中不存在的键时也存在潜在的问题(例如,如果相乘,如果任何字典缺少该键,则在最终结果中将得到0)。当然,也许这就是你真正想要的。

另请注意,上述所有内容均假设您的值为int。但是大多数代码都没有真正的假设。只要你有一些组合一对值的有效方法,你就可以轻松地修改上面的代码来做任何你想做的事情。这包括最终示例的完全通用版本:

Dictionary<TKey, TValue> Merge<TKey, TValue>(
    Dictionary<TKey, TValue>[] dictionaries, Func<TValue, TValue, TValue> mergeFunction)
{
    Dictionary<TKey, TValue> merged = new Dictionary<TKey, TValue>(dictionaries.First());

    foreach (Dictionary<TKey, TValue> dict in dictionaries.Skip(1))
    {
        foreach (var kvp in dict)
        {
            TValue value;

            merged.TryGetValue(kvp.Key, out value);
            merged[kvp.Key] = mergeFunction(kvp.Value, value);
        }
    }
}

(免责声明:上述代码均未编译。我提前为任何印刷错误道歉,并假设找出我真正的意思并不会太难:))。

最后,请注意Enumerable.ToDictionary() method。我已经编写了上面的一般逻辑,但您可能会发现可以使用各种LINQ操作(包括ToDictionary()方法)来简化代码并使其更能表达您的实际意图(即代码显示更多你想做什么,而不是 如何完成。