简体   繁体   中英

how to check key existence for dictionary within a dictionary in C#

In below code, how can I check key existence for dictionary within a dictionary?

Current execution throws key existence error.

Output, For Key "a", another key "X" with both values 1 and 2

Do we have any better collection for this?

 var data = new Dictionary<string, Dictionary<string, object>>();

        foreach (var j in GetTopData())
        {
            foreach (var p in BottomData())
            {
                if (data.Keys.Contains(j.ToString()))
                {
                    data[j].Add(p.Name, p.Value);
                }
                else
                {
                    data.Add(j, new Dictionary<string, object> { { p.Name, p.Value } });
                }
            }
        }

Here are the data classes,

private static List<TempData> BottomData()
    {
        return new List<TempData>
        {
            new TempData{ Name="X", Value=1},
            new TempData{ Name="X", Value=2}
        };
    }

    private static List<string> GetTopData()
    {
        return new List<string> { "a"};
    }

public class TempData
{
    public string Name { get; set; }
    public object Value { get; set; }
}

Your code could be simplified to:

        var data = new Dictionary<string, Dictionary<string, List<object>>>();

        foreach (var j in GetTopData())
        {
            foreach (var p in BottomData())
            {
                Dictionary<string, List<object>> values;
                var existed = data.TryGetValue(j, out values);

                if (!existed)
                    values = new Dictionary<string, List<object>>();

                List<Object> list;

                var existed2 = values.TryGetValue(p.Name, out list);
                if (!existed2)
                    list = new List<object>();

                list.Add(p.Value);

                if (!existed)
                    data.Add(j, values);

                if (!existed2)
                    values.Add(p.Name, list);
            }
        }

You'll need to check for existing data in both of the dictionaries. Currently you are checking existence in just one dictionary:

var data = new Dictionary<string, Dictionary<string, object>>();

            foreach (var j in GetTopData())
            {
                foreach (var p in BottomData())
                {
                    if(data.ContainsKey(j.ToString()))
                    {
                        var mydict = data[j.ToString()];
                        if (!mydict.ContainsKey(p.Name))
                            data[j].Add(p.Name, p.Value);
                    }
                    else
                    {
                        data.Add(j, new Dictionary<string, object> { { p.Name, p.Value } });
                    }
                }
            }

Because you need one key to contain multiple values, Dictionary<string, Dictionary<string, object>> will not work for you (it allows only 1 value for particular key). You can use Dictionary<string, Dictionary<string, List<object>>> , but it is hard to read and difficult to work with. So I thing it is better to use Dictionary, where both keys are combined into one as shown bellow in CombinedKey class (in C# 7.0, ValueTuple<string, string> will work too):

public class CombinedKey
{
    public string Key1;
    public string Key2;

    // It is necessary to override Equals and GetHashCode to make
    // it work properly as a dictionary key.
    public override bool Equals(object obj)
    {
        var otherCombinedKey = obj as CombinedKey;

        return otherCombinedKey != null
            && otherCombinedKey.Key1 == this.Key1
            && otherCombinedKey.Key2 == this.Key2;
    }

    public override int GetHashCode()
    {
        return Key1.GetHashCode() ^ Key2.GetHashCode();
    }
}

Then use it this way:

Dictionary<CombinedKey, List<object>> data = new Dictionary<CombinedKey, List<object>>();

foreach (var j in GetTopData())
{
    foreach (var p in BottomData())
    {
        var key = new CombinedKey() { Key1 = j, Key2 = p.Name };
        List<object> list;
        if(!data.TryGetValue(key, out list))
        {
            data[key] = list = new List<object>();
        }
        list.Add(p.Value);
    }
}

If your data are immutable, you could also use Lookup<CombinedKey, object> class instead.

Answer to your question how to check key existence for dictionary within a dictionary in C# :

You can check this by using Linq like this example :

bool keyExistance = data.Any(x=>x.Value.ContainsKey(keyTocheck));

But before that you have to fix the errors in your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM