C# 用C从一个列表中排除另一个列表中的项目#
关于如何从一个列表中排除另一个列表中的项目,我有一个相当具体的问题。诸如Except()之类的常用方法行不通,原因如下:C# 用C从一个列表中排除另一个列表中的项目#,c#,winforms,list,optimization,C#,Winforms,List,Optimization,关于如何从一个列表中排除另一个列表中的项目,我有一个相当具体的问题。诸如Except()之类的常用方法行不通,原因如下: 如果列表中的副本有一个“偶数”索引,我需要删除这个元素和它后面的下一个元素 如果列表中的副本有一个“奇数”索引,我需要删除这个元素和它前面的一个元素 同一个重复项在列表中可能有许多外观。i、 一个指数可能是“奇数”,另一个指数可能是“偶数” 我不是在要求一个解决方案,因为我自己创造了一个。然而,在多次执行此方法之后,“ANTS performance profiler”显
- 如果列表中的副本有一个“偶数”索引,我需要删除这个元素和它后面的下一个元素
- 如果列表中的副本有一个“奇数”索引,我需要删除这个元素和它前面的一个元素
- 同一个重复项在列表中可能有许多外观。i、 一个指数可能是“奇数”,另一个指数可能是“偶数”
private void removedoubles(List<int> exclude, List<int> listcopy)
{
for (int j = 0; j < exclude.Count(); j++)
{
for (int i = 0; i < listcopy.Count(); i++)
{
if (listcopy[i] == exclude[j])
{
if (i % 2 == 0) // even
{
//listcopy.RemoveRange(i, i + 1);
listcopy.RemoveAt(i);
listcopy.RemoveAt(i);
i = i - 1;
}
else //odd
{
//listcopy.RemoveRange(i - 1, i);
listcopy.RemoveAt(i - 1);
listcopy.RemoveAt(i - 1);
i = i - 2;
}
}
}
}
}
private void removedoubles(列表排除,列表复制)
{
对于(int j=0;j
其中:
- 排除-仅包含重复项的列表。此列表最多可包含30个元素
- listcopy—应检查重复项的列表。如果发现“排除”中的重复项->执行删除操作。此列表最多可包含2000个元素
我认为LINQ可能会有所帮助,但我不太理解它的语法。反转循环,使循环从
.Count-1
开始,然后转到0,这样在其中一种情况下就不必更改I
,并且Count
只在每个集合中计算一次 更快的方法(O(n)
)是执行以下操作:
exclude
列表并将其放入HashSet
(O(n)
)O(n)
),因为在HashSet
中存在的测试是O(1)
exclude
集合从一开始就是一个HashSet
,这样您就可以省略步骤1并获得更快的速度
(您当前的方式是O(n^2)
)
编辑:
另一个想法是:您可能正在创建某个列表的副本,并让此方法修改它?(根据参数名进行猜测。)然后,您可以将其更改为:将原始数组传递给该方法,并使该方法分配新数组并返回它(您的方法签名应该是类似于
private List getWithoutDoubles(HashSet exclude,List original)
)
编辑:
如果您以以下方式重新组织输入数据,则速度可能会更快:由于项目总是成对删除(偶数索引+以下奇数索引),因此您应该提前将它们配对!因此,如果int的列表变为int对的列表。这样,您的方法可能类似于:
private List<Tuple<int, int>> getWithoutDoubles(
HashSet<int> exclude, List<Tuple<int, int>> original)
{
return original.Where(xy => (!exclude.Contains(xy.Item1) &&
!exclude.Contains(xy.Item2)))
.ToList();
}
private List getwithout doubles(
哈希集排除,列表原始)
{
返回原始.Where(xy=>(!exclude.Contains(xy.Item1))&&
!exclude.Contains(xy.Item2)))
.ToList();
}
(删除排除集合中第一项或第二项所在的对)。您可以将项目打包为自定义类型,而不是
元组。您可以将列表转换为LinkedList并试一试吗?List.RemoveAt()比LinkedList.Remove()更昂贵 这里是获得结果的另一种方法
var a = new List<int> {1, 2, 3, 4, 5};
var b = new List<int> {1, 2, 3};
var c = (from i in a let found = b.Any(j => j == i) where !found select i).ToList();
var a=新列表{1,2,3,4,5};
var b=新列表{1,2,3};
var c=(在let found=b.Any(j=>j==i)中,其中!found select i.ToList();
c将包含4,5粗体和大写字母,在我看来太多了。这是为了显示主要思想。无论如何,编辑了issueahh-永远不要更改for
循环中的循环变量!使用while循环代替!您正在调用Count()
方法,它是LINQ的一部分。这可能比简单地使用Count
属性要慢,该属性已内置在列表中*去编码他不是在叫计数,他是在叫计数()
。第一个只是List
类的一个属性,另一个是LINQ-我想,将代码更改为使用该属性而不是方法将是一个很大的改进。@Alex:请注意,如果您是倒计时,您需要更改要删除的项的索引计算。这也很好,因为它只需要一个循环,并自动从“待删除”列表中删除两个循环。