eddwo wrote:
I seem to be forever coming across the following situation.
I have a set of key-value mapping of type List<KeyValuePair<K,V>>
eg: { a -> 5, b-> 7, c -> 12, d -> 7, e -> 5, f -> 12, g -> 9 }
which I then need to invert so that I can retrieve the set of unique values with their associated keys.
List<KeyValuePair<V,List<K>>
eg: { 5 -> {a,e}, 7 -> {b,d}, 9 -> {g}, 12 -> {c,f} }
(sort order of result is unimportant, just shown sorted for readability)
With C# 2.0 I'll usually have something like
//where Type V implements IComparable
SortedList<V,List<K>>> Invert(List<KeyValuePair<K,V>> list)
{
SortedList<V,List<K>> output = new SortedList<V,List<K>>;
foreach(KeyValuePair<K,V> pair in list)
{
if (!output.ContainsKey(pair.Value))
{
List<K> set = new List<K>();
set.Add(pair.Key);
output.Add(pair.Value,set);
}
else
{
output[pair.Value].Add(pair.Key);
}
}
return output;
}
I'm sure there must be a much better a way of expressing this transformation in Linq or in other functional programming languages as a simple expression with a lambda for supplying the value equality comparison function.
I don't know what its called or how to go looking for it, but it must be a pretty common operation for other people in all sorts of situations, and something that would probably be fairly parallelisable.
I do not have a nice code sample but to start with in linq:
your "list" can be used in a query as it it was a sql table, so you can
do
from ____
Where _____
select ____
that will handle the main for loop for you.
linq has grouping and the select can allow a new() that can return a new "shape" of data.
in linq you can say something like:
new { a = foo.y, b = foo.bar, c = foo.duh }
and if you started with
var subset = from ....
then you can do stuff like:
foreach ( var item in subset )
{
}
or whatever ...
the var [name] behaves like a list / collection and has a .tolist() method.
look at the blogs by scott gu for more info:
http://weblogs.asp.net/scottgu/archive/2007/09/07/linq-to-sql-part-9-using-a-custom-linq-expression-with-the-lt-asp-linqdatasource-gt-control.aspxwhile his set is on dlinq it's almost all the same stuff...
just think in terms of set operations, try to let linq do the for loops.
I hope that helps you get started...