我在foreach循环中有一个foreach循环,如下所示:
// Item is an abstract class. Item1, Item2, etc. are his heirs.
List<Item> allItems = new List<Item> { new Item1(), new Item2(), new Item3(), new Item4() };
List<Type> affectedItems = new List<Type> { typeof(Item1), typeof(Item3) };
foreach(Item i in allItems)
foreach(Type t in affectedItems)
if(i.GetType().Equals(t))
{
// does something
}
如何改进我的代码,以便内部循环不会浪费那么多时间检查列表中不存在的项目?
答案 0 :(得分:5)
li.level1
,Where
)都是一个额外的循环。您需要最小化循环次数(尤其是嵌套循环次数),在您的情况下,最好的方法是使用快速查找数据结构:
Any
到目前为止,这是最快的方法,循环次数最少,并且需要 0.02毫秒,而其他方法需要 0.7 。
快速建议,无论何时进行循环处理,您希望优化查找要使用的数据结构,如List<Item> allItems = new List<Item>{ new Item1(), new Item2(), new Item3(), new Item4() };
HashSet<Type> affectedItems = new HashSet<Type>(){ typeof(Item1), typeof(Item3) };
foreach (Item i in allItems)
{
if (affectedItems.Contains(i.GetType()))
{
// Do Something
}
}
,HashSet
,Dictionary
,等。
答案 1 :(得分:2)
像这样编写单循环:
foreach (Item i in allItems.Where (item => affectedItems.
Any (type => type.Equals (item.GetType ()))))
这将仅返回allItems
中来自affectedItems
的类型的项目。
与您的代码的唯一区别是Any
将在找到第一个类型后停止搜索。这是唯一的改进。但您可以在break
声明中添加if
。那么这两个代码片段将是等效的。
答案 2 :(得分:1)
如果你有一个很大的类型列表,那么将列表更改为HashSet可能有助于提高性能,否则它没有太大的区别。
List<Item> allItems = new List<Item> { new Item1(), new Item2(), new Item3(), new Item4() };
HashSet<Type> affectedItems = new HashSet<Type> { typeof(Item1), typeof(Item3) };
var items = allItems.Where(item=> affectedItems.Contains(item.GetType()));
foreach(var item in items)
{
// does something
}
答案 3 :(得分:0)
这是最快的(我尝试你的代码,Linq有交叉和这个):
Array.ForEach(allItems.ToArray(), i => {
var t = i.GetType();
if (affectedItems.Contains(t)) {
// Do Something
}
});