如何删除Collection中的重复对象?这就是我试过的:
dim unique_students as Collection
dim no_duplicate_student as cls_Student
dim no_duplication as boolean
For Each student as cls_Student In list_Student 'list_Students = original unsorted collection
no_duplication = True
Dim s As cls_Student
For Each s In unique_students
If s.name = student.name Then
no_duplication = False 'Duplication found
Exit For
End If
next s
If no_duplication Then
'Inserted into new sorted collection if no values matches that of the sorted collection
Set no_duplicate_student = New clsOverlap
no_duplicate_student.name = student.name
unique_students.Add no_duplicate_student
End If
Next student
然而,这仍然需要很长时间(if list_Student.Count > 5000
,然后运行需要30分钟+)。是否有更有效的方法(如果可能,减少时间复杂度)删除集合中的重复?
答案 0 :(得分:1)
将学生姓名添加到词典,其中包含.Exists
方法,以检查项目是否已存在于词典中。
您可以在Collection And Dictionary Procedures
中的CollectionToDictionary
获取一些想法
For Each student
循环中的类似内容:
If Dict.Exists(Key:=student.name) Then
' is duplicate!
Else
Dict.Add Key:=student.name, Item:=student.name
' you could also do Item:=student if you want the de-duplicated list in a dictionary
End If
不需要内循环。该功能几乎可以瞬间运行。
答案 1 :(得分:1)
我通常使用像Andre451建议的字典。或者你可以像这样使用ArrayList。我不确定两者之间是否存在很大的性能差异,但如果需要,此方法也会生成一个排序列表。字典虽然可以携带键/值对,但它只取决于你要追求的东西。
<div id="container">
<img id="image" src="http://www.noao.edu/image_gallery/images/d4/androa.jpg" />
<p id="text">
Hello World!
</p>
</div>
编辑:经过测试,我确认字典方法的速度大约是7.7秒的两倍,而百万分之13秒。但是,在OP计数为5000时,差异仅为40 vs 80 ms。
在此测试代码......
Error in arima.sim(model = list(ar = c(3, 0, 5)), n = 50) :'ar' part of
model is not stationary
再次编辑:好的,所以我发现这非常有趣。最重要的似乎是实际类型本身。因此,例如,上面的测试创建了一个ArrayList,从中可以派生出唯一值。如果将其更改为基本整数数组Sub Demo()
Set AL = CreateObject("System.Collections.ArrayList")
AL.Add "A"
AL.Add "B"
AL.Add "A"
AL.Add "A"
AL.Add "C"
'Sorting allows sequential comparisons to determine uniqueness
'You could also do something similar to the dictionary method with ArrayList.Contains
'but the evluation of ArrayList.Contains runs slower than this
AL.Sort
For i = 0 To AL.Count - 2
If AL(i) <> AL(i + 1) Then
'Prints unique values
Debug.Print AL(i)
End If
Next
If AL(i) <> AL(i - 1) Then
'Prints last value if unique by comparing to one before it
Debug.Print AL(i)
End If
End Sub
,则时间从7.7秒减少到0.8秒。同样,只需在排序操作之后添加行Public Declare Function GetTickCount Lib "kernel32.dll" () As Long
Sub DictionaryDemo()
Set D = CreateObject("Scripting.Dictionary")
Set AL = CreateObject("System.Collections.ArrayList")
For i = 0 To 10 ^ 6
AL.Add Round(Rnd * 10, 0)
Next
Start = GetTickCount
For i = 0 To AL.Count - 1
If Not (D.Exists(AL(i))) Then
D.Add AL(i), ""
Debug.Print AL(i)
End If
Next
Debug.Print GetTickCount - Start
End Sub
Sub ArrayListDemo()
Set AL = CreateObject("System.Collections.ArrayList")
For i = 0 To 10 ^ 6
AL.Add Round(Rnd * 10, 0)
Next
'Sorting allows sequential comparisons to determine uniqueness
Start = GetTickCount
AL.Sort
For i = 0 To AL.Count - 2
If AL(i) <> AL(i + 1) Then
'Prints unique values
Debug.Print AL(i)
End If
Next
If AL(i) <> AL(i - 1) Then
'Prints last value if unique by comparing to one before it
Debug.Print AL(i)
End If
Debug.Print GetTickCount - Start
End Sub
并循环遍历数组Dim AL(10 ^ 6) As Integer
,就可以将ArrayList方法从13秒缩减到0.5秒。
这是有道理的,因为数组的内存分配允许它们被非常快速地处理。这也是为什么有些人喜欢创建他们自己的排序和唯一性算法,而不是采用效率较低但易于使用的方法,采用最初建议的Dictionary或ArrayList。字典和ArrayLists仍然是强大的工具,如上所述,他们仍然可以在几分之一秒内从100万长度中提取独特的值,但值得注意的是,当涉及到原始效率时,一个简单的数组很快就会变坏循环。
以下代码将在约0.3秒内从100万个长度数组中提取唯一值。它与OP没有太大的不同,但效率更高。这是因为循环收集的速度非常慢,不是因为基本策略的效率低下。此外,请注意,随着唯一值的数量增加,效率将降低(此测试仅使用1-10的10个唯一值)。
A = AL.ToArray