将foreach循环转到Linq

本文关键字:Linq 循环 foreach | 更新日期: 2023-09-27 18:26:27

是否有要写的东西?将每个循环的这个变成Linq表达式:

private List<string> datasetItemset;
Dictionary<string, int> itemsetScanning = new Dictionary<string, int>();
List<string> itemList = new List<string>();
foreach (string transaction in this.datasetItemset)
{
    string[] items = transaction.Split(new char[] { ' ' });
    foreach (string item in items)
        if (!itemList.Contains(item))
        {
            itemList.Add(item);
            itemsetScanning.Add(item, 0);
        }
}

我的下一个问题是,使用linq表达式而不是foreach循环是否会加快程序的性能,我对这个linq有点陌生。

更新:使用过多的foreach循环会减慢我的程序速度。

将foreach循环转到Linq

使用linq表达式而不是foreach循环确实提高了程序的性能,我对这个linq有点陌生。

没有。在内部,LINQ通常仍然会执行相同数量的迭代,所以一般来说,它不会加快速度。如果编写得当,LINQ将执行与循环非常相似的操作。

使意图更加清晰是非常有用的,这反过来有时可以使优化变得更简单,缩短流程。也就是说,同样的优化也可以很容易地在循环上完成。

有没有什么可以写的?把每个循环的这个变成Linq表达式:

是的。这可以通过以下方式完成:

foreach(var item in this.datasetItemset
   .SelectMany(transaction => transaction.Split(' '))
   .Distinct())
{
    itemList.Add(item);
    itemsetScanning.Add(item, 0);
}

请注意,内部主体/循环被保留为foreach循环,在这种情况下,这是故意的,因为它正在执行副作用。

假设你正在构建列表和集合,你可以使用:

var itemList = this.datasetItemset.SelectMany(transaction => transaction.Split(' ')).ToList();
var uniqueSet = new HashSet<string>(itemList); // Build the set from the list

这将为您提供一组唯一的值(作为HashSet<string>)以及值列表。如果你只需要一个唯一的值列表,你可以使用Distinct直接构建它:

 var uniqueItemList = this.datasetItemset
                          .SelectMany(transaction => transaction.Split(' '))
                          .Distinct()
                          .ToList();

如果你需要字典,那么它只需要以下结果:

var itemsetScanning = uniqueItemList.ToDictionary(i => i, i => 0);

这里是丑陋的linq

foreach (var item in this.datasetItemset
    .Select(transaction => transaction.Split(new char[] { ' ' }))
    .SelectMany(items => items
        .Where(item => !itemList.Contains(item))))
    {
        itemList.Add(item);
        itemsetScanning.Add(item, 0);
    }
List<string> itemList = this.datasetItemset
    .SelectMany(item => item.Split(' '))
    .Distinct()
    .ToList();
var itemsetScanning = itemList.ToDictionary(e => e, _ => 0);

关于性能,Linq将比精心设计的特定解决方案慢,但它通常足够快。如果性能对您来说是一个问题,您可能应该避免它(在分析之后)。

以下是我如何编写代码:

var itemList = datasetItemset.SelectMany(transaction => transaction.Split(' '))
    .Distinct()
    .ToList();
var itemsetScanning = itemList.ToDictionary(transaction => transaction,
    transaction => 0);

这是解决问题的更惯用的LINQ方法。

嵌套的foreach通常映射到SelectMany调用,您可以使用Distinct,而不是检查该项是否已经存在,它不仅在语义上表示您要做的事情,而且会明显更高效(因为您避免了在列表中重复线性搜索;如果您愿意,您可以在非LINQ解决方案中使用HashSet来更高效地搜索)。您可以使用ToListToDictionary将每个序列直接转换为集合,而不是将项添加到集合中,以避免显式使用foreach

您可以使用LINQ:轻松完成同样的操作

var itemList = this.datasetItems
                   .SelectMany(x => x.split(' '))
                   .Distinct()
                   .ToList();
var itemssetScanning = itemList.ToDictionary(x => x, x => 0);

然而,在SelectManyDistinctToListToDictionary方法中仍然隐藏着foreach循环这里没有魔法额外的委托调用会使其速度慢于自定义循环。