Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从列表中删除对象<;对象>;当列表包含相同的对象而不创建新列表时_C#_Linq - Fatal编程技术网

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);
}