5

I have a list like:

List<String> test = new List<String> {"Luke", "Leia"};

I would like to use something like this:

test.Select(s => String.Format("Hello {0}", s));

but it doesn't adjust the names in the list. Is there a way to use lambda expressions to alter these? Or is it because strings are immutable that this doesn't work?

4 Answers 4

12

Select doesn't modify the original collection; it creates a new IEnumerable<T> that you can enumerate with a foreach or convert to a list:

List<String> test2 = test.Select(s => String.Format("Hello {0}", s)).ToList();

test still contains "Luke" and "Leia", and test2 contains "Hello Luke" and "Hello Leia".


If you want to modify the original list with a lambda expression, you can apply the lambda expression to each list item individually and store the result back in the collection:

Func<string, string> f = s => String.Format("Hello {0}", s);

for (int i = 0; i < test.Count; i++)
{
    test[i] = f(test[i]);
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, the first one succeeded for me.
@Nyla Pareska: That version does not modify the original collection which seemed to be your intent ("but it doesn't adjust the names in the list"). If you want to do that, please see the extension method that I provided in my answer.
3

Here:

for(int i = 0; i < test.Count; i++) {
    test[i] = String.Format("Hello {0}", test[i]);
}

No need to be fancy. No need to abuse LINQ. Just keep it simple.

You could go one step beyond this and create an extension method like so:

static class ListExtensions {
    public static void AlterList<T>(this List<T> list, Func<T, T> selector) {
        for(int index = 0; index < list.Count; index++) {
            list[index] = selector(list[index]);
        }
    }
}

Usage:

test.AlterList(s => String.Format("Hello {0}", s));

Select is for projecting and is really intended to be used in circumstances where there are no side-effects. Manipulating the items in the list very clearly has side-effects. In fact, the line

test.Select(s => String.Format("Hello {0}", s));

doesn't do anything except creating an IEnumerable<string> that could eventually be enumerated over to produce the projection.

7 Comments

I don't understand how he would be abusing LINQ. He would be using it exactly as it was intended to be used. His question also specifically asked how to perform the task using a lambda expression.
Select is not meant to be used for causing side effects.
I did. My apologies for not mentioning it in my original comment. When I read over the original question, I must have skimmed over the part where he said he was trying to alter the list of strings. In that circumstance, I will agree that LINQ is not an appropriate tool to use.
@Justin Rusbatch: (Responding to the edit of your comment.) Yes, he asked about lambda expression. He also asked specifically about using Select. Trying to fenagle Select to modify the list would be an abuse of LINQ. As for using lambda expressions, I have provided an extension method that does the job.
Yep, we're in agreement now -- I will undo my downvote. I read your answer with the assumption that he would enumerate over the list projected by Select, but looking back over his question I see that he was indeed trying to modify the list he had.
|
0

One other possible solution:

List<String> test = new List<String> {"Luke", "Leia"};
List<string> FormattedStrings = new List<string>();
test.ForEach(testVal => FormattedStrings.Add(String.Format("Hello {0}", testVal)));

Comments

-2

You could just do a foreach statement:

test.ForEach(s=>String.Format("Hello {0}", s));

That is if you are trying to just update the names.

6 Comments

ForEach takes an Action<T> and does not modify the List<T>
String.Format returns a new string, but does not modify the original string.
Ok, so update it as such: s=> s = String.Format("Hello {0}", s)); It all depends on what he was wanting to do anyway, return a new list with updated values or update the original list.
ForEach(s=> s = String.Format("Hello {0}", s))) doesn't do anything as well.
dtb-> Sorry, my bad, I'm so used to using Reference types that I can modify that I forgot value types work differently in this scenario. In this case you would have to use the for(;;) syntax to accomplish the same thing.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.