【问题标题】:Use select() instead of foreach loop使用 select() 而不是 foreach 循环
【发布时间】:2019-02-13 19:26:06
【问题描述】:

有没有办法使用 linq select 来简化这段代码

我想从我的列表中删除一些项目并将新项目添加到具有相同索引的列表中。下面的代码有效..我正在检查这是否可以使用 LINQ select 语句而不是 foreach 来简化。

if (newHits.Any())
{
    int newHitIndex = 0;
    foreach (var h in allHits.ToList())
    {
        if (h.Type == type)
        {
            var index = allHits.FindIndex(a => a.Hit == h.Hit);
            var newHit = newHits[newHitIndex];
            allHits.RemoveAt(index);
            allHits.Insert(index, newHit);
            newHitIndex++;
        }
    }
}

【问题讨论】:

  • Linq 的Select 用于选择并可能对集合成员执行操作。它不应该用于删除和重新添加集合中的项目。在我看来,Linq 不是完成此类任务的最佳方式,我认为这不是它应该用于的。
  • 有一种方法可以使用 LINQ 完成其中的一些操作,但最终可能不会像您想要的那样干净。话虽如此,肯定还有其他方法可以使这段代码更干净。 newHitsallHits 是什么类型?
  • Hit 是唯一键吗? var index = allHits.FindIndex(a => a.Hit == h.Hit);是不是在找h的索引?
  • 您可以通过过滤列表来删除ifforeach (var h in allHits.Where(hit => hit.Type == type))

标签: c# linq


【解决方案1】:

我认为这是相同的代码,但通过首先选择索引,然后过滤Type 是我们关心的项目,稍微简化了代码。我们还删除了if (newHits.Any()),因为这并不能真正防止我们从allHits 中选择比newHits 包含的更多项目(在原始代码中,我们盲目地递增并使用newHitIndex 而不检查边界newHits)。

看看这是否适合你:

int newHitIndex = 0;

foreach (var index in allHits.Select((item, index) => index)  // Select the index
    .Where(i => allHits[i].Type == type))                     // Filter on Type
{
    if (newHitIndex == newHits.Count) break;   // Stop when we get to the end of newHits
    allHits[index] = newHits[newHitIndex++];   // Set value and increment in one line
}

另一种方法是选择我们想要更改为List<int>allHits 项目的索引,获取CountnewHits.Count 中较小的一个,然后在for循环做我们的任务:

var allHitsIndexes = allHits.Select((item, index) => index)
    .Where(i => allHits[i].Type == type).ToList();

var maxCount = Math.Min(newHits.Count, allHitsIndexes.Count);

for (var i = 0; i < maxCount; i++)
{
    allHits[allHitsIndexes[i]] = newHits[i];
}

【讨论】:

    【解决方案2】:
    if (newHits.Any())
    {
        int newHitIndex = 0;
        var allHitsList = allHists.ToList();
        for(var index =0; index < allHitsList.Count; ++index)
        {
            var h = allHitsList[index]
            if (h.Type == type)
            {
                var newHit = newHits[newHitIndex];
                allHitsList[index] = newHit;
                newHitIndex++;
            }
        }
    }
    

    然后将allHitsList 转换为allHits 的任何类型。

    【讨论】:

    • 您可以通过将第 4 行更改为 var allHitsList = allHits.Where(h =&gt; h.Type == type).ToList(); 来进一步简化此操作,这样您就可以删除 if 检查。
    • @Abion47:那么我们将使用部分列表而不是完整列表。我们需要在正确索引处包含 type 对象的完整列表。
    • 正如它所写的那样,您正在对allHitsList 进行所有处理和替换,这不会影响allHits(除非allHits 本身就是List,在这种情况下@987654331 @ 和随后的分配无论如何都是多余的)。您当前使用index 的唯一目的是获取/设置生成列表中index 的值,无论是完整列表还是部分列表都无关紧要。
    • @Abion47,正确,这就是为什么我在末尾添加了关于将AllHitsList 转换为AllHits 的行——因为我不知道AllHits 是什么类型。但关键是,AllHitsList 是 AllHits 外观的精确复制品。您的方式可以简化为 newHits.ToList() -- 但我们需要替换 AllHits 中的特定点。
    猜你喜欢
    • 2012-01-27
    • 2014-10-23
    • 2021-12-11
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    相关资源
    最近更新 更多