C# - 使用lambda表达式或LINQ填充列表

NRa*_*Raf 3 c# linq lambda

已经有一段时间了,因为我已经使用了lambda表达式或LINQ,并且我想知道如何使用这两种方法执行以下操作(我知道我可以使用foreach循环,这只是出于好奇).

我有一个字符串路径数组(如果这是一个数组或列表,它会有所不同吗?)我想从中返回一个只有文件名的新列表.

即使用foreach循环,它将是:

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

return listToReturn;
Run Code Online (Sandbox Code Playgroud)

我如何用lambda和LINQ做同样的事情?

编辑:在我的情况下,我使用返回的列表作为ListBox(WPF)的ItemsSource所以我假设它将需要是一个列表而不是IEnumerable?

Hen*_*man 15

您的主要工具是.Select()方法.

string[] paths = getPaths();
var fileNames = paths.Select(p => Path.GetFileName(p));
Run Code Online (Sandbox Code Playgroud)

如果这是一个数组或列表,它会有所作为吗?

不,数组也实现了 IEnumerable<T>


请注意,这种最小化方法涉及延迟执行,这意味着它fileNames是一个IEnumerable<string>并且只有在从它获取元素时才开始迭代源数组.

如果你想要一个List(为了安全),请使用

string[] paths = getPaths();
var fileNames = paths.Select(p => Path.GetFileName(p)).ToList();
Run Code Online (Sandbox Code Playgroud)

但是当有许多文件时,您可能希望通过使用延迟执行源来反向(使结果交错,更快):

var filePaths = Directory.EnumerateFiles(...);  // requires Fx4
var fileNames = filePaths.Select(p => Path.GetFileName(p));
Run Code Online (Sandbox Code Playgroud)

这取决于你接下来要做什么fileNames.

  • @Jon:你有一个很好的观点(我同意;简短的解释将会取而代之),但我经常看到人们使用`List <T>`只是因为他们不知道替代品,所以我倾向于喜欢"及时停止"的答案.我并不是说OP没有意识到这一点,但帖子中没有任何内容表明实际上需要"IEnumerable <T>"提供的任何东西(除了变量声明). (2认同)

Jon*_*eet 6

我认为"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();
Run Code Online (Sandbox Code Playgroud)

通过从方法组构造投影委托来注意最后一个如何工作,如下所示:

Func<string, string> projection = Path.GetFileName;
var listToReturn = paths.Select(projection).ToList();
Run Code Online (Sandbox Code Playgroud)

(以防万一不清楚.)

请注意,如果您不需要将其用作列表 - 如果您只想迭代它,换句话说 - 您可以ToList()从这些方法中删除每个方法.


dig*_*All 5

只是:

var listToReturn = getPaths().Select(x => Path.GetFileName(x)).ToList();
Run Code Online (Sandbox Code Playgroud)

正如在其他答案中已经说明的那样,如果你实际上不需要a,List<string>你可以省略ToList()并简单地返回IEnumerable<string>(例如,如果你只需要迭代它,IEnumerable<>更好,因为避免创建另一个字符串列表)

此外,假设该Select()方法采用委托,并且方法组和具有相同签名的委托之间存在隐式转换,则可以跳过lambda并执行以下操作:

getPaths().Select(Path.GetFileName)
Run Code Online (Sandbox Code Playgroud)