Anybody have a slicker way to do this? Seems like it should be easier than this, but I'm having a mental block. Basically I need to remove items from an dictionary and recurse into the values of the items that are also dictionaries.
private void RemoveNotPermittedItems(ActionDictionary menu)
{
var keysToRemove = new List<string>();
foreach (var item in menu)
{
if (!GetIsPermitted(item.Value.Call))
{
keysToRemove.Add(item.Key);
}
else if (item.Value is ActionDictionary)
{
RemoveNotPermittedItems((ActionDictionary)item.Value);
if (((ActionDictionary)item.Value).Count == 0)
{
keysToRemove.Add(item.Key);
}
}
}
foreach (var key in (from item in menu where keysToRemove.Contains(item.Key) select item.Key).ToArray())
{
menu.Remove(key);
}
}
Action dictionary is like this:
public class ActionDictionary : Dictionary<string, IActionItem>, IActionItem
You don't really need to collect the keys and iterate them again if you iterate the dictionary in reverse (from 'menu.Count - 1' to zero). Iterating in forward order will, of course, yield mutated collection exceptions if you start removing things.
I don't know what an ActionDictionary is, so I couldn't test your exact scenario, but here's an example using just Dictionary<string,object>.
static int counter = 0;
private static void RemoveNotPermittedItems(Dictionary<string, object> menu)
{
for (int c = menu.Count - 1; c >= 0; c--)
{
var key = menu.Keys.ElementAt(c);
var value = menu[key];
if (value is Dictionary<string, object>)
{
RemoveNotPermittedItems((Dictionary<string, object>)value);
if (((Dictionary<string, object>)value).Count == 0)
{
menu.Remove(key);
}
}
else if (!GetIsPermitted(value))
{
menu.Remove(key);
}
}
}
// This just added to actually cause some elements to be removed...
private static bool GetIsPermitted(object value)
{
if (counter++ % 2 == 0)
return false;
return true;
}
I also reversed the 'if' statement, but that was just an assumption that you'd want to do type checking before calling a method to act on the item's value...it will work either way assuming 'GetIsPermitted' always returns TRUE for ActionDictionary.
Hope this helps.
While foreach and GetEnumerator fails, a for-loop works,
var table = new Dictionary<string, int>() {{"first", 1}, {"second", 2}};
for (int i = 0; i < table.Keys.Count; i++)//string key in table.Keys)
{
string key = table.Keys.ElementAt(i);
if (key.StartsWith("f"))
{
table.Remove(key);
}
}
But ElementAt() is a .NET 3.5 feature.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With