我有一个User对象列表,我必须从列表中删除一个具有特定UserID的项目。
此方法必须尽可能快,目前我循环遍历每个项目并检查ID是否与UserID匹配,如果没有,则将该行添加到我的filteredList集合中。
List allItems = GetItems();
for(int x = 0; x < allItems.Count; x++)
{
if(specialUserID == allItems[x].ID)
continue;
else
filteredItems.Add( allItems[x] );
}
答案 0 :(得分:8)
如果确实必须尽可能快,请使用不同的数据结构。列表未知删除效率。将ID映射到用户的词典怎么样?
答案 1 :(得分:4)
好吧,如果你想创建一个新的集合来保持原始的不变,你必须循环遍历所有项目。
从头开始创建具有正确容量的新列表,以最大限度地减少分配。
continue
的程序逻辑似乎有点倒退......只需使用!=运算符而不是==运算符:
List<User> allItems = GetItems();
List<User> filteredItems = new List<User>(allItems.Count - 1);
foreach (User u in allItems) {
if(u.ID != specialUserID) {
filteredItems.Add(u);
}
}
如果您想更改原始集合而不是创建新集合,则将项目存储在Dictionary<int, User>
中将是最快的选择。定位项目并将其删除都接近O(1)操作,这样可以使整个操作接近O(1)操作而不是O(n)操作。
答案 2 :(得分:3)
使用哈希表。对于一切假设具有最小碰撞潜力的良好散列算法的查找时间是O(1)。我会推荐一些实现IDictionary的东西
答案 3 :(得分:2)
如果您必须从一个列表转移到另一个列表,这是我找到的禁食结果:
var filtered = new List<SomeClass>(allItems);
for (int i = 0; i < filtered.Count; i++)
if (filtered[i].id == 9999)
filtered.RemoveAt(i);
我尝试比较你的方法,上面的方法和linq“where”语句:
var allItems = new List<SomeClass>();
for (int i = 0; i < 10000000; i++)
allItems.Add(new SomeClass() { id = i });
Console.WriteLine("Tests Started");
var timer = new Stopwatch();
timer.Start();
var filtered = new List<SomeClass>();
foreach (var item in allItems)
if (item.id != 9999)
filtered.Add(item);
var y = filtered.Last();
timer.Stop();
Console.WriteLine("Transfer to filtered list: {0}", timer.Elapsed.TotalMilliseconds);
timer.Reset();
timer.Start();
filtered = new List<SomeClass>(allItems);
for (int i = 0; i < filtered.Count; i++)
if (filtered[i].id == 9999)
filtered.RemoveAt(i);
var s = filtered.Last();
timer.Stop();
Console.WriteLine("Removal from filtered list: {0}", timer.Elapsed.TotalMilliseconds);
timer.Reset();
timer.Start();
var linqresults = allItems.Where(x => (x.id != 9999));
var m = linqresults.Last();
timer.Stop();
Console.WriteLine("linq list: {0}", timer.Elapsed.TotalMilliseconds);
结果如下: 测试开始
转移到已过滤的清单:610.5473
从筛选列表中删除:207.5675
linq list:379.4382
使用“Add(someCollection)”并使用“.RemoveAt”的速度更快。
此外,后续.RemoveAt调用非常便宜。
答案 4 :(得分:1)
我知道它不是最快的,但是通用列表和删除()呢? (msdn)。任何人都知道它与例如相比如何表现。问题中的例子?
答案 5 :(得分:1)
这是一个想法,你怎么不删除它本身。我的意思是这样的:
public static IEnumerable<T> LoopWithExclusion<T>(this IEnumerable<T> list, Func<T,bool> excludePredicate)
{
foreach(var item in list)
{
if(excludePredicate(item))
{
continue;
}
yield return item;
}
}
关键是,只要你需要一个“过滤”列表,只需调用这个循环遍历原始列表的扩展方法,返回所有项目,除了你不想要的项目。
这样的事情:
List<User> users = GetUsers();
//later in the code when you need the filtered list:
foreach(var user in users.LoopWithExclusion(u => u.Id == myIdToExclude))
{
//do what you gotta do
}
答案 6 :(得分:1)
假设列表的计数是偶数,我会:
(a)获取处理器数量列表
(b)将列表划分为每个处理器的相等块
(c)为每个具有这些数据块的处理器生成一个线程,终止条件是如果发现谓词返回一个布尔标志。
答案 7 :(得分:1)
public static void RemoveSingle<T>(this List<T> items, Predicate<T> match)
{
int i = -1;
while (i < items.Count && !match(items[++i])) ;
if (i < items.Count)
{
items[i] = items[items.Count - 1];
items.RemoveAt(items.Count - 1);
}
}
答案 8 :(得分:0)
我无法理解为什么最简单,直接和明显的解决方案(也是基于List
的解决方案中最快的解决方案)并非由任何人提供。
此代码删除具有匹配ID的一个项目。
for(int i = 0; i < items.Count; i++) {
if(items[i].ID == specialUserID) {
items.RemoveAt[i];
break;
}
}
答案 9 :(得分:0)
如果您有一个列表,并且您希望在适当的位置进行变异以删除符合条件的项目,则以下内容比目前发布的任何备选项目更快:
for (int i = allItems.Count - 1; i >= 0; i--)
if (allItems[i].id == 9999)
allItems.RemoveAt(i);
对于某些用途,Dictionary
可能会更快,但不要对List
进行折扣。对于小型集合,它可能会更快,对于大型集合,它可以节省内存,这可能反过来使您的应用程序整体更快。分析是确定实际应用程序中哪个更快的唯一方法。
答案 10 :(得分:-1)
如果您有数百或数千个项目,以下是一些有效的代码:
List allItems = GetItems();
//Choose the correct loop here
if((x % 5) == 0 && (X >= 5))
{
for(int x = 0; x < allItems.Count; x = x + 5)
{
if(specialUserID != allItems[x].ID)
filteredItems.Add( allItems[x] );
if(specialUserID != allItems[x+1].ID)
filteredItems.Add( allItems[x+1] );
if(specialUserID != allItems[x+2].ID)
filteredItems.Add( allItems[x+2] );
if(specialUserID != allItems[x+3].ID)
filteredItems.Add( allItems[x+3] );
if(specialUserID != allItems[x+4].ID)
filteredItems.Add( allItems[x+4] );
}
}
如果循环的大小可以被最大数字整除到最小数字,则开始测试。如果你想在循环中使用10个if语句,那么测试列表的大小是否大于10并且可以被10整除然后从那里向下。例如,如果你有99个项目---你可以在循环中使用9个if语句。循环将迭代11次而不是99次
“if”语句便宜且快速