views:

42

answers:

4

How could I construct a LINQ expression to remove values from one list that meet the criteria of a function that returns a boolean?

string[] message = "days of the week"
message.ToList().RemoveAll(c=>checkShortWord(c));

public static bool checkShortWord(string word) {
       if ((word.Length > 3) &&                        
          (!Regex.IsMatch(word, "^[0-9]+$")))          
        return true;

      return false;
}

My ending string array should now be:

message = {"days","week"}

What should I change? My message array never changes.

+1  A: 

Three things. One, message is not an array (I'm assuming it is in your real code). Two, your method is backwards. Three, you're not retaining a reference to the list.

var list = message.ToList();
list.RemoveAll(word=>word.Length <= 3 || Regex.IsMatch(word, "^[0-9]+$"));

If you can't change/eliminate the method (e.g. you use it elsewhere):

var list = message.ToList();
list.RemoveAll(word=>!checkShortWord(word));
Matthew Flaschen
+3  A: 

You are constructing a new List and removing the items from that list, and then throwing it away. If you want an array that is missing the removed items, you will need to create a new one:

string[] message = "days of the week".Split(' ');
message = message.Where(c => checkShortWord(c)).ToArray();

Alternately, you could use a List<String> instead of a string[], and then use the RemoveAll method to modify it in place:

List<string> message = "days of the week".Split(' ').ToList();
message.RemoveAll(c => !checkShortWord(c));

As others have mentioned, you have also named your predicate method badly. "IsLongWord" might be more appropriate. You could write it a little more simply like this:

public static bool IsLongWord(string word)
{
    return word.Length > 3 && !Regex.IsMatch(word, "^[0-9]+$");
}
Quartermeister
Ah .. okay .. I will try this. Thanks !
sidd.darko
+1  A: 

Don't name your method checkShortWork. That's confusing. Name it after what it really checks, e.g. IsShortWord. Then your lambda expression looks like this:

message.ToList().RemoveAll(c => IsShortWord(c));

In other words, remove all members of list that are short words. Of course, you also need to assign your result to a variable if you want to do anything with it.

Also, in your current function, your true and false appear to be backwards.

Kyralessa
+1  A: 

Assuming you actually have a list (IEnumerable<string>) rather than your incorrect message variable, and that checkShortWord actually returns true for short words, then you'd do this:

IEnumerable<string> before = new [] {"days", "of", "the", "week"};
IEnumerable<string> after = before.Where(word => !checkShortWord(word)); 
Enigmativity