I would do an extension method :
public static class DictionaryExt
{
public static IEnumerable<T> PartialMatch<T>(this Dictionary<string, T> dictionary, string partialKey)
{
// This, or use a RegEx or whatever.
IEnumerable<string> fullMatchingKeys =
dictionary.Keys.Where(currentKey => currentKey.Contains(partialKey));
List<T> returnedValues = new List<T>();
foreach (string currentKey in fullMatchingKeys)
{
returnedValues.Add(dictionary[currentKey]);
}
return returnedValues;
}
}
The "cost" of adding values to the dictionary wouldn't change, but the cost of retrieval would be higher, but only when you know you're going with a partial match.
Btw, I'm sure you could transform this in a single Lambda expression, but the concept remains the same.
Edit: In your example, this method would return 2 lists of values, but you can change it to merge the lists. Here is the extension method you could do :
public static IEnumerable<T> PartialMatch<T>(
this Dictionary<string, IEnumerable<T>> dictionary,
string partialKey)
{
// This, or use a RegEx or whatever.
IEnumerable<string> fullMatchingKeys =
dictionary.Keys.Where(currentKey => currentKey.Contains(partialKey));
List<T> returnedValues = new List<T>();
foreach (string currentKey in fullMatchingKeys)
{
returnedValues.AddRange(dictionary[currentKey]);
}
return returnedValues;
}
Edit 2: Come to think of it, you could also make it more generic. With the next extension method, it would work on any dictionary, as long as you provide a comparer
that check what you mean by "partial match" :
public static IEnumerable<TValue> PartialMatch<TKey, TValue>(
this Dictionary<TKey, IEnumerable<TValue>> dictionary,
TKey partialKey,
Func<TKey, TKey, bool> comparer)
{
// This, or use a RegEx or whatever.
IEnumerable<TKey> fullMatchingKeys =
dictionary.Keys.Where(currentKey => comparer(partialKey, currentKey));
List<TValue> returnedValues = new List<TValue>();
foreach (TKey currentKey in fullMatchingKeys)
{
returnedValues.AddRange(dictionary[currentKey]);
}
return returnedValues;
}