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.