Datasheet
The Delegate Strategy
x
15
{
foreach (T it in data)
yield return (transform(it));
}
In terms of their purpose, Filter is the easiest to grasp — it applies the Predicate to each element
in the
Database and includes that element if the Predicate returns true.
Map is less obvious — it applies a Func (an operation) to each element in the Database, transform-
ing it into something else, usually (though not always) of a different type. If, for example, the system
needs to extract a list of all the
Students’ ages, Map can transform the Student into an age:
foreach (int a in
Students.Map(delegate(Student it)
{ return it.Age; }))
{
Console.WriteLine(a);
}
The last, Reduce, is the most complicated, largely because it is the most fundamental — both Map
and
Filter could be rewritten to use Reduce. Reduce takes the collection, a delegate that knows
how to extract a single bit of information from the element and perform some operation on it to
yield a rolling result and hand that back. The easiest thing to do with
Reduce is obtain a count of all
the elements in the collection, by incrementing that accumulator value each time:
int count =
Students.Reduce(0, delegate(Student st, int acc)
{
return acc++;
});
Or if for some reason the total of all the Students’ ages added together were important, Reduce can
produce it by adding the age to the accumulator each time through:
int sumAges =
Students.Reduce(0, delegate(Student st, int acc)
{
return st.Age + acc;
});
In truth, this is useless information — what would be much more interesting is the average of all the
Students’ ages, but this is a bit trickier to do with Reduce — because the average is defi ned as the
total divided by the number of elements in the collection, Reduce has to be used twice:
float averageAge =
(Students.Reduce(0, delegate(Student st, float acc)
{
return st.Age + acc;
}))
/
(Students.Reduce(0, delegate(Student st, float acc)
c01.indd 15c01.indd 15 10/1/2010 3:20:38 PM10/1/2010 3:20:38 PM