C# 从列表中删除对象<;对象>;当列表包含相同的对象而不创建新列表时
我有C# 从列表中删除对象<;对象>;当列表包含相同的对象而不创建新列表时,c#,linq,C#,Linq,我有 var a=新对象(); var b=新对象(); var c=新对象(); var d=新对象(); var e=新对象(); var list=新列表{a,b,c,d,e,a,d}; 然后我需要删除最后两个对象(a和d),因为它们已经在列表中了。 如何在不创建新列表的情况下执行此操作?如果调用List.Remove它将删除第一个实例;但是,您可以使用list.RemoveAt和list.removeange。例如: var a = new object(); var b = ne
var a=新对象();
var b=新对象();
var c=新对象();
var d=新对象();
var e=新对象();
var list=新列表{a,b,c,d,e,a,d};
然后我需要删除最后两个对象(a
和d
),因为它们已经在列表中了。如何在不创建新列表的情况下执行此操作?如果调用
List.Remove
它将删除第一个实例;但是,您可以使用list.RemoveAt
和list.removeange
。例如:
var a = new object();
var b = new object();
var c = new object();
var d = new object();
var e = new object();
var list = new List<object> {a, b, c, d, e, a, d};
或者更好:首先不要添加它们
例如,如果要从序列中添加,则可以在添加时使用Distinct
或HashSet
查找唯一项
事后,您可以使用:
list.RemoveRange(5,2);
删除除第一个副本外的所有副本
或者更有效地:
var dups = from item in list
group item by item into grp
where grp.Count() > 1
select grp.Key;
foreach (var val in dups)
{
int first = list.IndexOf(val), last;
while ((last = list.LastIndexOf(val)) != first)
{
list.RemoveAt(last);
}
}
for(int i=0;i
如何在不创建新列表的情况下完成
您的需求有些令人惊讶(或者至少您没有解释为什么必须修改列表很重要),但这里有一个有利于提高内存使用速度的解决方案:
for (int i = 0; i < list.Count; i++ )
{
var val = list[i];
int first = list.IndexOf(val), last;
while ((last = list.LastIndexOf(val)) != first)
{
list.RemoveAt(last);
}
}
我当然更喜欢第二种解决方案,但它不能满足您的要求。您可以将此向后用于循环和
可枚举。包含
+列表。移除
。这不会创建新列表:
var list = list.Distinct().ToList();
var list=新列表{“a”、“b”、“c”、“d”、“e”、“a”、“d”};
对于(int i=list.Count-1;i>=0;i--)
{
var obj=列表[i];
if(列表获取(i)包含(obj))
列表。删除(i);
}
所以这个循环通过索引器获取一个对象,在索引之前获取所有对象,并相互比较。请注意,由于延迟执行,所以不会创建集合,将其理解为一个循环,它将在返回true
后立即结束。如果它已经可用,它将从列表中删除。所以早起的鸟儿有虫吃
但是,如果要支持自定义类型,则需要在类中重写Equals
和GetHashCode
,否则包含的
将只比较引用
是否可以首先阻止将这些对象附加到列表中?“不创建新列表”-此约束的真正含义是什么?创建一个新的列表并不是一个昂贵的操作。LINQ没有办法,因为它会临时为每个操作创建新的列表来完成任务。还有一个问题:为什么?@Damien_the_unsiver:为什么有人不想创建一个需要更多内存的新列表,从而增加了发生
OutOfMemoryException
?@TimSchmelter?这并不奇怪,因为这是一个不寻常的要求。由于有人误解了.NET/C的某些方面,经常会出现异常需求。所以问这个问题很有帮助(如果这个人真的愿意解释他们的理由也很有帮助),因为如果你了解他们的来历,你可能会为OP提供更多的实际帮助。但是如果没有任何其他类型的IEnumerable,他怎么会得到“2”?@Tigran这就是为什么(见上面的代码)我使用的是LastIndexOf
——避免了用画笔作为答案。最后一部分-我正在寻找的。已经是很好的答案了。对不起,我不能再接受一个了。只有+1您的要求有点令人惊讶
为什么有人不想创建需要更多内存的新列表,因此增加了OutOfMemoryException
的风险?如果根本问题是源列表非常大,不应该重复,那么我的解决方案就没有用,因为如果列表没有任何重复项,哈希集的备份存储将消耗与源列表相同的存储量。然而,尽管其他一些建议的解决方案不会消耗更多内存,但就所需CPU而言,它们的效率非常低,因为它们会重复搜索源列表中的重复项。这个解决方案通过使用更多的内存来避免这种低效。我只是想指出,即使备份集合是临时的,也有一个很好的理由来避免重复集合。如果程序需要几秒钟的时间(例如,如果它是windows服务),这可能并不重要,但它运行时不出现异常可能很重要。此外,如果循环方法对哈希集效率低下,则意味着集合非常大。那么记忆问题就更重要了。@TimSchmelter:完全同意。如果源代码非常大,并且内存是一个问题,那么我的解决方案就不好。然而,问题中没有具体说明为什么要修改清单。另一个可能的原因可能是由于涉及到第三方API,因此无法替换列表。
var list = list.Distinct().ToList();
var list = new List<object> { "a", "b", "c", "d", "e", "a", "d" };
for (int i = list.Count - 1; i >= 0; i--)
{
var obj = list[i];
if(list.Take(i).Contains(obj))
list.RemoveAt(i);
}