Interestingly, if you enumerate over the dictionary (length N) first and check the list (length M) for inclusion, then you get O(NM) performance.
You could build a HashSet<>
of the ids, but that seems redundant since we already have a (pre-hashed) dictionary available.
I would instead iterate over the ids first; since dictionary lookup (by key) is O(1), this gives O(M) performance - this might, however, mean that you don't use LINQ (since TryGetValue
won't love LINQ (and introducing a tuple is too much like hard work)...
Dictionary<string, string> getValidIds(
IDictionary<string, string> salesPersons,
IEnumerable<string> ids) {
var result = new Dictionary<string, string>();
string value;
foreach (string key in ids) {
if (salesPersons.TryGetValue(key, out value)) {
result.Add(key, value);
}
}
return result;
}
It doesn't overly concern me that this is more lines than the LINQ version; it removes an O(N) of complexity...
Edit; the following might work (I haven't tested it), but I think it is an abuse of LINQ, and certainly won't scale to PLINQ etc... use with extreme caution!! I also believe the foreach
approach simply has fewer overheads, so will be quicker... anyway:
Dictionary<string, string> getValidIds(
IDictionary<string, string> salesPersons,
IEnumerable<string> ids)
{
string value = null;
return (from key in ids
where salesPersons.TryGetValue(key, out value) // HACK: v. dodgy
select new { key, value })
.ToDictionary(x=>x.key, x=>x.value);
}