在C#中将Foreach转换为lambda或LINQ

vwhgwdsa  于 2023-05-20  发布在  C#
关注(0)|答案(3)|浏览(200)

如何将ELSE部分转换为单个Lambda或LINQ查询。
我想去掉多个for/foreach语句。我尝试了多种方法,但lamda查询没有给我想要的结果。
例如:在案例响应中,UResources没有数据(即空列表)
这里CurrentBS是列表,UResources是列表

List<BSS> noTask = new List<BSS>();

 if (response.CurrentBS.Count > 0 && 
     response.UResources != null && 
     response.UResources.Count == 0)
 {
     noTask = response.CurrentBS.Where(x => x.CurrentBS.TaskId == 0).ToList();
 }
 else
 {
     var bnt = response.CurrentBS.Where(x => x.CurrentBS.TaskId == 0).ToList();

     for (int index = bnt.Count() - 1; index >= 0; index--)
     {
         foreach (var uResource in response.UResources)
         {
             if (bnt[index].BotId.ToString().ToLower() == uResource.Name.ToLower()
                 && uResource.Type == ResourceType.Bot)
             {
                 bnt.RemoveAt(index);
             }
         }
     }

     noTask = bnt;
  }

数据输出应该只在这两种情况下

案例:1

List of CurrentBS
BotId | TaskId
101   | 0
102   | 0
103   | 0
104   | 0
105   | 0

List of UResource = empty list
Name | Type

Output should return all items from List of CurrentBS i.e 
101,102,103,104,105

案例:2

List of CurrentBS
BotId | TaskId
101   | 0
102   | 0
103   | 0
104   | 17
105   | 14

List of UResource

Name| Type
103 | Bot
104 | Bot 
105 | Bot 

Output should return items 101, 102 from list of CurrentBS

情况1为IF,情况2为ELSE

我可以有一个单一的查询两种情况下或2个单独的查询如果和否则。

mznpcxlj

mznpcxlj1#

很简单,只需在整个条件周围放置一个!,然后将其推入.Where。嵌套的foreach可以变成Any。您还可以合并if的两侧。
还要注意的是,您应该进行不区分大小写的比较,而不是使用ToLower

var results = response.CurrentBS.Where(x => x.CurrentBS.TaskId == 0);
if (!(response.CurrentBS.Count > 0 && 
     response.UResources != null && 
     response.UResources.Count == 0))
{
    results = results.Where(b =>
        !response.UResources.Any(r =>
            string.Equals(b.BotId.ToString(), uResource.Name, StringComparison.OrdinalIgnoreCase)
            && r.Type == ResourceType.Bot));
}
var noTask = results.ToList();
qmb5sa22

qmb5sa222#

这似乎符合您的标准:

IEnumerable<BSS> noTask = response.CurrentBS.Where(x => x.CurrentBS.TaskId == 0);

if (response.CurrentBS.Count <= 0 ||
    response.UResources == null ||
    response.UResources.Count != 0)
{
    var badBotNames = response.UResources
        .Where(uResource => uResource.Type == ResourceType.Bot)
        .Select(uResource => uResource.Name)
        .ToHashSet(StringComparer.OrdinalIgnoreCase);
    noTask = noTask.Where(x => !badBotNames.Contains(x.BotId.ToString()));
}

优点:

  • O(n)算法而不是O(n²)
  • 删除重复代码
  • 不会用一堆值填充列表,只是为了删除它们。
  • 避免不必要的ToString()ToLower()

奇怪的事情仍然困扰着我:

  • 如果response.UResources为null,则会抛出null引用异常。为什么在if中允许这样做?
  • 在示例输入中,BotId和Resource.name似乎是整数。为什么它们不都是整型的呢?如果它们有类似整数的字符串值,为什么要将它们转换为小写?

我可能会将代码简化为这样的代码,即使在某些情况下它可能会做更多的工作:

IEnumerable<BSS> noTask = response.CurrentBS.Where(x => x.CurrentBS.TaskId == 0);

if (response.UResources.Any())
{
    var badBotNames = response.UResources
        .Where(uResource => uResource.Type == ResourceType.Bot)
        .Select(uResource => uResource.Name)
        .ToHashSet(StringComparer.OrdinalIgnoreCase);
    noTask = noTask.Where(x => !badBotNames.Contains(x.BotId.ToString()));
}
7gcisfzg

7gcisfzg3#

看起来你总是用

List<BSS> items = response.CurrentBS.Where(x => x.CurrentBS.TaskId == 0).ToList();

现在,您只需要找出要删除的项目:

if(response.UResources?.Any() == true)
{
    items.RemoveAll(CheckIfRemove);
}

bool CheckIfRemove(Bss btn)
{
    return response.UResources
        .Any(r => r.Type == ResourceType.Bot 
               && StringComparer.OrdinalIgnoreCase.Equals(r?.Name, btn.BotId.ToString()));
}

相关问题