Predicates

D

Dom

I have the following (I'm using string, but it could be any class at
all):

List<string> m_List = new List <string> ();
m_List.Add ("Dominic");
m_List.Add ("Fred");
etc.

I would like to do the following (assume I have a TextBox "txt"):

m_List.FindIndex (txt.Text);

.... but it seems I need to write something called a Predicate. The
MSDN site is really useless here, and other examples I find in Google
just show me something called an anonymous predicate, which I don't
really like. Is there a good article on this, or can someone just
give me a quick example of what I need?

Thanks
Dom
 
D

Dom

For this purpose you simply need to use m_List.IndexOf(txt.Text).

A Predicate<T> is a particular sort of delegate (you can look up delegates
in the documentation): it's basically a pointer to a method that makes a
decision. You can use them for more advanced kinds of find, but simply
finding an item of the same value is built into List, as I described above.

Eq.

But that is true only of string's, right. If I had a List of
"person", an object of lastname, firstname, age, and so on, and I
wanted to find a person with the same last name only, I still need a
predicate. Or at least that is my understanding.

Dom
 
G

Gareth Erskine-Jones

But that is true only of string's, right. If I had a List of
"person", an object of lastname, firstname, age, and so on, and I
wanted to find a person with the same last name only, I still need a
predicate. Or at least that is my understanding.

Assuming you have a class called Person which has various properties
(such as FirstName, and LastName). Let's create a few persons (the
constructor takes the first and last name), and add them to a list:

Person p1 = new Person("John", "Doe");
Person p2 = new Person("Jane", "Doe");
Person p3 = new Person("Jane", "Smith");

List<Person> people = new List<Person> {p1, p2, p3};


// So now we have a list of three Person objects. Perhaps we want to
// find all of those who have "Doe" as the surname. You need to call
// the FindAll function on the list, providing a Predicate, which is a
// method with a particular signature.

List<Person> does = people.FindAll(findDoes);

// If "findDoes" is a predicate which takes a person and returns
// true if the person has the LastName equal to "Doe" then
// we should have a list of two items - John and Jane Doe.

// The predicate can be defined like this:

private static bool findDoes(Person person)
{
return (person.LastName == "Doe");
}



Now this is a bit awkward if you then want to find all the people
where FirstName equals "Jane". You have to define another predicate.
There are ways around this - you can create a class which takes the
parameter (what the first name should be) in the constructor and which
uses that when determining what to return in the predicate, but this
is a bit nasty.

Really the only thing you care about is the expression which describes
the items you want back, in this case:

person.LastName == "Doe"

So, we have anonymous delegates. You don't have to declare them, you
just use them inline. The line:

List<Person> does = people.FindAll(findDoes);

becomes:

List<Person> does = people.FindAll(delegate(Person person)
{
return person.LastName == "Doe";
});


// The delegate here is anonymous because it doesn't have a name
// (unlike "findDoes"). But it does the same thing, and if you need to
// search for FirstNames that equal "John", you can just alter it a
// bit:

List<Person> johns = people.FindAll(delegate(Person person)
{
return person.FirstName == "John";
});

// if you're using C# 3.0, there's an even more concise syntax
// available: the lambda expression:

List<Person> does3 = people.FindAll(person => person.LastName ==
"Doe");

HTH
 
B

Bart Tubalinal

Excellent example. Just to add to it a little bit, regarding use of
anonymous methods, in case it is not clear to Dom, you don't have to
necessarily hard-code the value that is to be evaluated against inside of
the anonymous method. Like the search for people with last names of Doe
below. That could be redone as:


string lastNameToFind = "Doe"; //this could come from a parameter or
wherever

List<Person> does = people.FindAll(delegate(Person person)
{
return person.LastName == lastNameToFind;
});
 
D

Dom

Excellent example. Just to add to it a little bit, regarding use of
anonymous methods, in case it is not clear to Dom, you don't have to
necessarily hard-code the value that is to be evaluated against inside of
the anonymous method. Like the search for people with last names of Doe
below. That could be redone as:

string lastNameToFind = "Doe"; //this could come from a parameter or
wherever

 List<Person> does = people.FindAll(delegate(Person person)
{
    return person.LastName == lastNameToFind;

});

--
Bart X. Tubalinalwww.deviantpoint.com























- Show quoted text -

Thanks to everyone for the examples. Its much clearer now.

Dom
 
P

Pavel Minaev

// if you're using C# 3.0, there's an even more concise syntax
// available: the lambda expression:

 List<Person> does3 = people.FindAll(person => person.LastName ==
"Doe");

If it comes to LINQ, then another option is:

var does3 = people.Where(p => p.LastName == "Doe");

which can be further sugared to be more SQL-like, if you prefer:

var does3 = from p in people
where p.LastName == "Doe"
select p;

Note though that in this case "does3" is of type IEnumerable<Person>,
not List<Person>. More often than not it is actually sufficient, but
if not, you can always do a ToList() on it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top