C#-将集合与自身进行比较以找到重复项的最快方法 公共类TestObject { 字符串TestValue{get;set;} bool是双重的{get;set;} } List testList=新列表 { 新的TestObject{TestValue=“Matt”}, 新的TestObject{TestValue=“Bob”}, 新的TestObject{TestValue=“Alice”}, 新的TestObject{TestValue=“Matt”}, 新的TestObject{TestValue=“Claire”}, 新的TestObject{TestValue=“Matt”} };

C#-将集合与自身进行比较以找到重复项的最快方法 公共类TestObject { 字符串TestValue{get;set;} bool是双重的{get;set;} } List testList=新列表 { 新的TestObject{TestValue=“Matt”}, 新的TestObject{TestValue=“Bob”}, 新的TestObject{TestValue=“Alice”}, 新的TestObject{TestValue=“Matt”}, 新的TestObject{TestValue=“Claire”}, 新的TestObject{TestValue=“Matt”} };,c#,collections,duplicates,C#,Collections,Duplicates,想象一下testList实际上有数百万个对象长 确保Matt的TestValue的三个TestObjects中的两个将其IsDuplicate设置为true的最快方法是什么?无论给定值的实例有多大,过程中只有一个实例的IsDuplicate of false 我并不反对通过线程来实现这一点。如果将集合转换为其他集合类型的速度更快,则该集合不必是列表 我需要保留副本并对其进行标记,而不是将其从集合中删除 扩展一下,这是(正如您可能想象的)一个更复杂问题的简单表达式。所讨论的对象已经有了一个序号,我

想象一下
testList
实际上有数百万个对象长

确保Matt的
TestValue
的三个
TestObjects
中的两个将其
IsDuplicate
设置为true的最快方法是什么?无论给定值的实例有多大,过程中只有一个实例的IsDuplicate of false

我并不反对通过线程来实现这一点。如果将集合转换为其他集合类型的速度更快,则该集合不必是列表

我需要保留副本并对其进行标记,而不是将其从集合中删除

扩展一下,这是(正如您可能想象的)一个更复杂问题的简单表达式。所讨论的对象已经有了一个序号,我可以用它来对它们进行排序

在精确匹配字符串相等的初始副本之后,我必须再次返回集合,并使用模糊匹配逻辑重新尝试剩余部分。在重复数据消除过程中或之后,不会更改此过程开始时存在的集合


最终,原始集合将被写入一个文件,并标记可能的重复项。

正如其他人提到的,正确的方法是使用HashSet类

public class TestObject
{
    string TestValue { get; set; }
    bool IsDuplicate { get; set; }
}

List<TestObject> testList = new List<TestObject>
{
    new TestObject { TestValue = "Matt" },
    new TestObject { TestValue = "Bob" },
    new TestObject { TestValue = "Alice" },
    new TestObject { TestValue = "Matt" },
    new TestObject { TestValue = "Claire" },
    new TestObject { TestValue = "Matt" }
};

我可能会在构建TestValue集合时检查重复项,以避免在数百万个元素上循环两次。如果这种情况是可能的,那么我将使用
字典

Dictionary myList=newdictionary();
while(NotEndOfData())
{
TestValue obj=GetTestValue();
if(myList.ContainsKey(对象名称))
{
obj.IsDuplicate=真;
myList[obj.Name].Add(obj);
}
其他的
{
obj.IsDuplicate=假;
添加(obj.Name,new List(){obj};
}
}
SortedSet sorted=新的SortedSet();
for(int i=0;i

正如您在问题中所允许的那样,我将
testList
更改为数组而不是列表,以加快索引器的速度。

因为您指出您有一个保留项目序号的属性。在将项目标记为重复项后,我们可以使用该属性将排序顺序重置为原始顺序

下面的代码是自我解释的。但是如果你需要进一步解释,请告诉我

我假设属性名为
SortOrder
。请相应地修改代码

SortedSet<string> sorted = new SortedSet<string>();
for (int i = 0; i < testList.Count; i++)
  testList[i].IsDuplicate = !sorted.Add(testList[i].TestValue);
void MarkDuplicates()
{
testList=testList.OrderBy(f=>f.TestValue).ThenBy(f=>f.SortOrder.ToList();
for(int i=1;if.SortOrder.ToList();
}

我不是性能专家。但您可以对此处提供的各种解决方案计时,并亲自检查性能。

这可能非常有效:

void MarkDuplicates()
{
    testList = testList.OrderBy(f => f.TestValue).ThenBy(f => f.SortOrder).ToList();
    for (int i = 1; i < testList.Count; i++) 
    {
        if (testList[i].TestValue == testList[i - 1].TestValue) testList[i].IsDuplicate = true;
    }
    testList = testList.OrderBy(f => f.SortOrder).ToList();
}

[编辑]这个方法的速度大约是上述公认答案的三分之一,因此应该使用这个方法。这个答案只是学术上的兴趣。

我不确定是否是这样,但如果您只需要不同的TestObject实体,那么就使用HashSet。它将为您提供最好的服务,因为它只包含特定类型的唯一实例e、 我也在想同样的@Anatolyevich,但是它不允许集合包含副本并标记副本。我假设这就是OP想要的。@Nasreddine匆忙涂鸦伪代码:)是的,我需要保留副本并标记它们。副本的意义是什么?这是否意味着您希望保留顺序,并且该顺序对于进一步处理集合很重要?标记重复项后,集合会发生什么情况?你打算如何处理这些复制品?您是否考虑过使用单独的
HashSet
进行重复检查,例如,当您添加一个新项目时,您会检查它是否已经在
HashSet
中,如果已经存在,您会立即将其标记为重复?如果列表中有第三个
Matt
,会发生什么情况?
Dictionary<string, List<TestValue>> myList = new Dictionary<string, List<TestValue>>();
while(NotEndOfData())
{
     TestValue obj = GetTestValue();
     if(myList.ContainsKey(obj.Name))
     {
         obj.IsDuplicate = true;
         myList[obj.Name].Add(obj);
     }
     else
     {
         obj.IsDuplicate = false;
         myList.Add(obj.Name, new List<TestValue>() { obj};
     }
}
SortedSet<string> sorted = new SortedSet<string>();
for (int i = 0; i < testList.Count; i++)
  testList[i].IsDuplicate = !sorted.Add(testList[i].TestValue);
void MarkDuplicates()
{
    testList = testList.OrderBy(f => f.TestValue).ThenBy(f => f.SortOrder).ToList();
    for (int i = 1; i < testList.Count; i++) 
    {
        if (testList[i].TestValue == testList[i - 1].TestValue) testList[i].IsDuplicate = true;
    }
    testList = testList.OrderBy(f => f.SortOrder).ToList();
}
foreach (var dupe in testList.GroupBy(x => x.TestValue).SelectMany(g => g.Skip(1)))
    dupe.IsDuplicate = true;