C # - заполнить список, используя лямбда-выражения или LINQ - PullRequest
3 голосов
/ 24 марта 2011

Прошло много времени с тех пор, как я использовал лямбда-выражения или LINQ, и мне интересно, как бы я поступил следующим образом (я знаю, что могу использовать цикл foreach, это просто из любопытства), используя оба метода.

У меня есть массив строковых путей (имеет ли значение, если это массив или список здесь?), Из которого я хочу вернуть новый список только имен файлов.

т.е. с помощью цикла foreach это будет:

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

return listToReturn;

Как бы я поступил так же с лямбдой и LINQ?

РЕДАКТИРОВАТЬ: В моем случае я использую возвращенный список в качестве ItemsSource для ListBox (WPF), поэтому я предполагаю, что это должен быть список в отличие от IEnumerable?

Ответы [ 5 ]

15 голосов
/ 24 марта 2011

Ваш основной инструмент - метод .Select ().

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

имеет ли значение, если здесь массив или список?

Нет, массив также реализует IEnumerable<T>


Обратите внимание, что этот минимальный подход включает отложенное выполнение , что означает, что fileNames является IEnumerable<string> и начинается итерация по исходному массиву только тогда, когда вы получаете элементы из него.

Если вы хотите, чтобы список (был безопасным), используйте

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

Но когда есть много файлов, вы можете пойти в обратном направлении (получить результаты с чередованием, быстрее)также используется отложенное выполнение источник:

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

Это зависит от того, что вы хотите сделать дальше с fileNames.

6 голосов
/ 24 марта 2011

Я думаю, что под «LINQ» вы действительно подразумеваете «выражение запроса», но:

// 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();

Обратите внимание, как работает последнее, создавая делегат проекции из группы методов, например:

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

(на всякий случай, если это не было ясно.)

Обратите внимание, что , если , вам не нужно использовать это как список - если вы просто хотите перебрать его, другими словами - вы можете отбросить вызов ToList() для каждого из этих подходов.

5 голосов
/ 24 марта 2011

Это просто:

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

Как уже говорилось в других ответах, если вам на самом деле не нужен List<string>, вы можете опустить ToList() и просто вернуть IEnumerable<string> (например, есливам просто нужно выполнить итерацию, IEnumerable<> лучше, потому что избегает создания другого списка строк)

Кроме того, учитывая, что метод Select() принимает делегата, и существует неявное преобразование между группами методов иделегаты, имеющие одинаковую подпись, вы можете пропустить лямбду и просто сделать:

getPaths().Select(Path.GetFileName)
4 голосов
/ 24 марта 2011

Вы можете сделать это так:

return getPaths().Select(Path.GetFileName);
1 голос
/ 24 марта 2011
listToReturn = paths.ToList().Select(p => Path.GetFileName(p));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...