优化C#代码以在嵌套循环中计算出现次数

3
我希望优化这段代码以计算字符串列表中出现次数的数量。具体来说,我有两个列表:
1)cat:一个包含重复项(必须存在)的大量字符串列表。
2)cat_unq:从cat中提取的不同元素。
目前我的代码循环遍历cat_unq中的所有唯一元素,并计算重复列表中唯一元素出现的次数。搜索在移动设备上运行。
我已经尝试使用数组代替列表,但性能稍微提高了一些,但并不足够。
另一种尝试是使用foreach parallel进行并行搜索,但性能不稳定。
以下是我当前正在使用的代码:
private List<int> GetCategoryCount(List<string> cat, List<string> cat_unq)
{
    List<int> cat_count = new List<int>();
    for (int i = 0; i < cat_unq.Count; i++)
        cat_count.Add(cat.Where(x => x.Equals(cat_unq[i])).Count());
    return cat_count;
}

cat_unq 是否包含 cat 的所有唯一值或其子集?如果是前者,您可以对 cat 进行分组并获取每个出现次数的计数。即使是后者,也最好在 cat 列表的一次遍历中获取这些计数,然后使用它按所需顺序获取计数。 - juharr
@TimSchmelter 这里不会有太大的帮助,因为它们会迭代cat_unq中的所有值,然后迭代cat中的值。 - juharr
@TimSchmelter 这要看情况。也许 cat_unq 代表了某种期望的顺序。但实际上,这似乎几乎像是他们可能会预先获取不同的值,然后执行比所需更多的工作。 - juharr
1个回答

5

之所以慢是因为您正在搜索每个唯一名称的整个cat数组。 (cat.Where(....).Count())。

相反,将带有重复项的猫列表分组,并将其作为字典。然后您可以快速找到每个唯一名称的数量。

private List<int> GetCategoryCount(List<string> cat, List<string> cat_unq)
{
    var catsDict = cat.GroupBy(x => x).ToDictionary(k => k.Key, v => v.Count());
    return cat_unq.Select(c => catsDict[c]).ToList();
}

请注意,如果你在其他地方形成你独特的猫名单是没有意义的,你可以在上面一起完成(字典将独特的猫名作为键)。
// No need for a separate list of unique names
private List<int> GetCategoryCount(List<string> cat)
{
    return cat.GroupBy(x => x).Select(g => g.Count()).ToList();
}

或许你实际想要的是一个包含所有唯一名称以及计数的列表

// No need for a separate list of unique names - as this one returns it with the counts in a dictionary
private Dictionary<string,int> GetCategoryCount(List<string> cat)
{
    return cat.GroupBy(x => x).ToDictionary((k => k.Key, v => v.Count());
}

需要注意的一点是,当cat和cat_unq中的类别大小相同时,这将是相当快的。如果cat_unq包含的类别数量明显少于cat_unq,则可能会进行许多不必要的分组。但我建议对这种情况进行分析。 - Euphoric
@Euphoric 是的(哦,还有感谢您的编辑!)。虽然我们需要有很多猫才能在分组中获得额外的周期,才能产生差异。 - Jamiec

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接