Reputation: 321
I have this dictionary.
private Dictionary<string[], ICommand> commandsWithAttributes = new Dictionary<string[], ICommand>();
And I need to find element in commandsWithAttributes
by part of the key. What I mean:
"-?"
- is a key that I use to find item.
({"-t","--thread"},ICommand)
({"-?","--help"},ICommand)
<- this is what I need to find.
Upvotes: 2
Views: 3287
Reputation: 642
This pair {"-t","--thread"}
is called a command line option. -t
is the short name of the option and --thread
is its long name. When you query the dictionary to get an entry by partial key, you actually want it indexed by the short name. Let's assume that:
Then we can have this comparer:
public class ShortNameOptionComparer : IEqualityComparer<string[]>
{
public bool Equals(string[] x, string[] y)
{
return string.Equals(x[0], y[0], StringComparison.OrdinalIgnoreCase);
}
public int GetHashCode(string[] obj)
{
return obj[0].GetHashCode();
}
}
... and plug it into the dictionary:
private Dictionary<string[], ICommand> commandsWithAttributes = new Dictionary<string[], ICommand>(new ShortNameOptionComparer());
To lookup a command we have to use a string[]
that contains only the short name i.e. -t
: var value = dictionary[new [] { "-t" }]
. Or wrap this inside an extension method:
public static class CompositeKeyDictionaryExtensions
{
public static T GetValueByPartialKey<T>(this IDictionary<string[], T> dictionary, string partialKey)
{
return dictionary[new[] { partialKey }];
}
}
... and use it to get the value:
var value = dictionary.GetValueByPartialKey("-t");
Upvotes: 1
Reputation: 2417
private Dictionary<string[], ICommand> commandsWithAttributes = new Dictionary<string[], ICommand>();
private ICommand FindByKey(string key)
{
foreach (var p in commandsWithAttributes)
{
if (p.Key.Any(k => k.Equals(key)))
{
return p.Value;
}
}
return null;
}
And Invoke like
ICommand ic = FindByKey("-?");
Upvotes: -1
Reputation: 5353
You can search by iterating all the keys
var needle = "-?";
var kvp = commandsWithAttributes.Where(x => x.Key.Any(keyPart => keyPart == needle)).FirstOrDefault();
Console.WriteLine(kvp.Value);
but it wouldn't give you any advantage from using Dictionary because you need to iterate over all the keys. It's better to flatten your hierarchy first and search for specific key
var goodDict = commandsWithAttributes
.SelectMany(kvp =>
kvp.Key.Select(key => new { key, kvp.Value }))
.ToDictionary(x => x.key, x => x.Value);
Console.WriteLine(goodDict["-?"]);
Upvotes: 0
Reputation: 601
Please, don't do this. Dictionaries are optimized for a one-key to one-value search.
My suggestion to use multiple keys to a single value is the following:
private Dictionary<string, ICommand> commandsWithAttributes = new Dictionary<string, ICommand>();
var command1 = new Command(); //Whatever
commandsWithAttributes.Add("-t", command1);
commandsWithAttributes.Add("--thread", command1);
var command2 = new Command(); //Whatever
commandsWithAttributes.Add("-?", command2);
commandsWithAttributes.Add("--help", command2);
Upvotes: 6