1

无论如何要为每个循环编写将其转换为 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 循环会减慢我的程序。

4

5 回答 5

6

使用 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

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

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

如果您需要字典,那么它只是获取这些结果:

var itemsetScanning = uniqueItemList.ToDictionary(i => i, i => 0);
于 2013-08-05T20:48:55.673 回答
1

这是丑陋的 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);
    }
于 2013-08-05T20:49:50.110 回答
1
List<string> itemList = this.datasetItemset
    .SelectMany(item => item.Split(' '))
    .Distinct()
    .ToList();

var itemsetScanning = itemList.ToDictionary(e => e, _ => 0);

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

于 2013-08-05T20:50:32.983 回答
1

以下是我将如何写出该代码:

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

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

嵌套的 foreach 通常映射到一个SelectMany调用,而不是检查该项目是否已经存在,您可以使用Distinct它,这不仅在语义上表示您正在尝试做的事情,而且会明显更有​​效(因为您避免重复的线性搜索通过列表;如果需要,您可以使用 aHashSet在非 LINQ 解决方案中更有效地搜索)。除了将项目添加到集合中,您还可以使用ToListand将每个序列直接转换为集合ToDictionary,以避免显式使用 a foreach

于 2013-08-05T20:56:36.687 回答
0

您可以使用 LINQ 轻松地做同样的事情:

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

var itemssetScanning = itemList.ToDictionary(x => x, x => 0);

但是,在 、和方法中仍然foreach隐藏着循环。这里没有魔法!额外的委托调用使其比自定义循环更慢。SelectManyDistinctToListToDictionary

于 2013-08-05T20:51:49.457 回答