I have the following List(Of String) defined in my program:

MyList:
1Test
2test
3
4Test
5

I would like to remove the word "Test" (regardless of capitalization) from each item in the list if it exists.

I know I can accomplish this using the following LINQ statment:

MyList = (From MyEntry As String In MyList
          Select UCase(MyEntry).Replace("TEST", "")).ToList

To get the final result:

MyList:
1
2
3
4
5

Now, just for the sake of learning Linq, I wanted to try doing it using different commands (and maybe even benchmarking them just to see which could be the best / most efficient). So I wanted to try:

MyList.ForEach(Function(MyEntry As String) MyEntry = UCase(MyEntry).Replace("TEST", ""))

But it doesn't seem to update the list.

I'm assuming this is because ForEach doesn't replace the data being iterated over, but I wanted to hear from any LINQ experts out there what your thoughts are / what you would suggest as being the nicest / most elegant solution to accomplish this.

share|improve this question
    
nicest / most elegant solution for such a simple case that requires only a single Select? – I4V May 22 '13 at 20:32
    
Well, I tried to create as simplistic an example as possible for the sake of illustration of my point / question... The bigger question was that I assumed the ForEach would be faster and yet did not work as expected at all and I'm just trying to understand as much about this as possible.... – John Bustos May 22 '13 at 20:40
up vote 3 down vote accepted

LINQ is meant for reading data, which you can act upon. It is not used to change data. You can, however, read the old set, process, get the new set, and then overwrite the old set with it, but it will not be faster than just working against the original List via a For loop. So your best bet is probably this:

Dim lst As New List(Of String)({"1Test", "2test", "3", "4Test", "5"})
For i = 0 To lst.Count - 1
  lst(i) = Regex.Replace(lst(i), "test", "", RegexOptions.IgnoreCase)
Next
share|improve this answer
    
Thanks for the additional example with the For loop. As for the LINQ ForEach method - It will not work because LINQ is only looking at the data for the sake of querying rather than has the functionality within it to update it? Am I understanding you correctly? Forgive my ignorance... I'm just trying to learn as much as possible here to become a better programmer.... – John Bustos May 22 '13 at 20:59
1  
@JohnBustos: Yes, data coming into the ForEach method is meant to be immutable, similar to a regular for..each loop. Suppose you have the above as For Each s As String In lst, you would not be able to change s there. – Neolisk May 22 '13 at 21:02
    
Thanks, @Neolisk, that makes PERFECT sense!!!! – John Bustos May 22 '13 at 21:04
1  
@JohnBustos: Keep in mind that your ForEach is actually calling a method of a generic list, not LINQ. It exists in .NET 2.0. – Neolisk May 22 '13 at 21:07

It doesn't update the list because you're not updating the list. Your function is getting a variable called MyEntry passed into it, and you're overwriting the variable, but doing nothing to put the new value back into the list. And it's a good thing, too, because if you did put the modified value back into the list, you'd probably get an exception about the collection being modified during enumeration.

I would stick with your original version that replaces the entire list with a modified version, or else do a normal for loop rather than a foreach loop.

share|improve this answer
    
Thanks, @Joel, that actually does make perfect sense... Between that and Neolisk giving the example of a simple, normal, For Each loop, it makes perfect sense and just seems kinda silly now!! - I guess that's a good thing :) – John Bustos May 22 '13 at 21:06

Try this

static void Main(string[] args)
    {
        List<string> lst = new List<string>() { "1Test", "2Test","33", "3test" };
        var q = from T in lst
                select new
                {
                    NewT = T.ToUpper().Replace("TEST", "")
                };
        Console.WriteLine("");

        int i = 0;
        foreach (var str in q.ToList())
        {
            lst[i++] = str.NewT;
            Console.WriteLine(str.NewT);

        }
        Console.Read();
    }

and here is the results

1
2
33
3
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.