【问题标题】:Using LINQ .Select and .Any in single line在单行中使用 LINQ .Select 和 .Any
【发布时间】:2020-01-31 19:37:21
【问题描述】:

如果可能的话,我希望优化一些代码以减少行数,并且不需要使用 LINQ 的“for 循环”。我看到一个类似的帖子在一行中询问 Select 和 Where,但并不完全相同。
假设我有:

fields”中具有属性“Id”和“Name”的元素列表,可以分别调用.Id.Name

Ex.  
fields[0] = Element  
fields[0].Id = 12345
fields[0].Name = Name01

我想创建一个新列表“filteredIds”,其中包含所选字段的 Id 属性。

This is the for loop version:  
List<Id> filteredIds = new List<Id>();
fields = {Element1, Element2, ...}; //List of Elements
List<string> selectedNames = new List<string>() {"Name01", "Name05", "Name10"};
foreach (Element e in fields):
          if (selectedNames.Contains(e.Name())
          {
          filteredIds.Add(e.Id);
          }

这可以在 LINQ 中像这样在一行中完成吗?

filteredIds = fields.Select(i => i.Id).Any(o => selectedNames.Contains(o.Name)).ToList();

【问题讨论】:

  • 我想知道您是否想过Select()Where() 是如何实现的?
  • 你快到了,filteredIds = fields.Where(o =&gt; selectedNames.Contains(o.Name)).Select(i =&gt; i.Id).ToList();
  • LINQ 不是 Siri。很抱歉成为一个糟糕的 stackoverflow 人,但这个问题只是显示零研究。
  • 您可以使用 HashSet 而不是 List 选择名称以使其更小更高效。

标签: c# linq for-loop


【解决方案1】:

Any() 返回 true/false 值。您需要调用Where() 来实际过滤结果。

filteredIds = fields.Where(o => selectedNames.Contains(o.Name)).Select(i => i.Id).ToList();

【讨论】:

  • 如果你把where 放在选择之后,你将没有o.Name 属性。对吗?
  • @SimonWilson 写了一个答案 :) 我的意思是你确实在上面的 cmets 中提供了一个解决方案......
  • @Çöđěxěŕ...是的,我知道。我认为这是一个“简单”的问题,所以在评论中给出了答案。下次吧。我猜只要 OP 得到他的答案
  • 谢谢坦维尔!
【解决方案2】:

几乎正确。您应该使用 Where 来过滤列表,而不是 Any。

如果列表中至少有一个元素满足谓词,则 Any 返回一个布尔值,而 Where 返回满足谓词的所有元素。

您还需要在 Select 之前应用 Where 过滤器,因为 name 属性已被 select 删除。

【讨论】:

  • 谢谢乔纳斯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多