NRaf
NRaf

Reputation: 7549

C# - Populate a list using lambda expressions or LINQ

It's been a while since I've used lambda expressions or LINQ and am wondering how I would do the following (I know I can use a foreach loop, this is just out of curiosity) using both methods.

I have an array of string paths (does it make a difference if it's an array or list here?) from which I want to return a new list of just the filenames.

i.e. using a foreach loop it would be:

string[] paths = getPaths();
List<string> listToReturn = new List<string>();
foreach (string path in paths)
{
    listToReturn.add(Path.GetFileName(path));
}

return listToReturn;

How would I do the same thing with both lambda and LINQ?

EDIT: In my case, I'm using the returned list as an ItemsSource for a ListBox (WPF) so I'm assuming it's going to need to be a list as opposed to an IEnumerable?

Upvotes: 5

Views: 39715

Answers (5)

Henk Holterman
Henk Holterman

Reputation: 273179

Your main tool would be the .Select() method.

string[] paths = getPaths();
var fileNames = paths.Select(p => Path.GetFileName(p));

does it make a difference if it's an array or list here?

No, an array also implements IEnumerable<T>


Note that this minimal approach involves deferred execution, meaning that fileNames is an IEnumerable<string> and only starts iterating over the source array when you get elements from it.

If you want a List (to be safe), use

string[] paths = getPaths();
var fileNames = paths.Select(p => Path.GetFileName(p)).ToList();

But when there are many files you might want to go the opposite direction (get the results interleaved, faster) by also using a deferred execution source:

var filePaths = Directory.EnumerateFiles(...);  // requires Fx4
var fileNames = filePaths.Select(p => Path.GetFileName(p));

It depends on what you want to do next with fileNames.

Upvotes: 18

David M&#229;rtensson
David M&#229;rtensson

Reputation: 7600

listToReturn = paths.ToList().Select(p => Path.GetFileName(p));

Upvotes: 1

digEmAll
digEmAll

Reputation: 57210

It's just:

var listToReturn = getPaths().Select(x => Path.GetFileName(x)).ToList();

As already stated in other answers, if you don't actually need a List<string> you can omit the ToList() and simply return IEnumerable<string> (for example if you just need to iterate it, IEnumerable<> is better because avoids the creation of an other list of strings)

Also, given that Select() method takes a delegate, and there's an implicit conversion between method groups and delegates having the same signature, you can skip the lambda and just do:

getPaths().Select(Path.GetFileName)

Upvotes: 5

Jon Skeet
Jon Skeet

Reputation: 1500055

I think by "LINQ" you really mean "a query expression" but:

// Query expression
var listToReturn = (from path in paths
                    select Path.GetFileName(path)).ToList();

// Extension methods and a lambda
var listToReturn = paths.Select(path => Path.GetFileName(path))
                        .ToList();

// Extension methods and a method group conversion
var listToReturn = paths.Select(Path.GetFileName)
                        .ToList();

Note how the last one works by constructing the projection delegate from a method group, like this:

Func<string, string> projection = Path.GetFileName;
var listToReturn = paths.Select(projection).ToList();

(Just in case that wasn't clear.)

Note that if you don't need to use this as a list - if you just want to iterate over it, in other words - you can drop the ToList() call from each of these approaches.

Upvotes: 6

Florian Greinacher
Florian Greinacher

Reputation: 14786

You could do it like this:

return getPaths().Select(Path.GetFileName);

Upvotes: 4

Related Questions