TL; DR:
有没有办法将类集合/列表传递给库排序算法,并让它返回一个排序列表(最好是命名/默认类属性)? /强>
我最近学习了一些Python,Sorted()
函数给我留下了深刻的印象,它可以对任何可迭代的函数进行排序。对于数字,这很简单,但对于类,可以分配比较方法like this。该方法告诉比较运算符如何比较该类的2个实例。除此之外,它还允许您使用内置排序算法对类的集合进行排序。
在VBA中,我已经成功地模仿了这一点。通过设置“default member Attribute
”类,您可以直接在类上使用比较运算符(<
,=
,>=
等)。以示例类为例:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "defaultProp"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private randVal As Single
Public Property Get DefaultValue() As Single
Attribute Value.VB_UserMemId = 0
DefaultValue = randVal
End Property
Private Property Let DefaultValue(ByVal value As Single)
randVal = value
End Property
Private Sub Class_Initialize()
DefaultValue = Rnd()
End Sub
可以比较这个类的两个实例:
Dim instance1 As New defaultProp
Dim instance2 As New defaultProp
Debug.Print instance1.DefaultValue > instance2.DefaultValue
Debug.Print instance1 > instance2 'exactly equivalent, as the DefaultValue has the correct Attribute
如果我正在实现可以对值进行排序的VBA排序算法,那么按默认值*排序类应该没有问题。但是我更喜欢使用内置/库排序算法(出于同样的原因,任何人都会这样做;清晰度,效率,正确的错误处理等)。
* these algorithms中的一个可以为此工作,但必须修改以循环整个类,而不是它的值(通过添加Set
s) < / p>
由于VBA比较运算符没有问题,我认为对于库所使用的任何内容都是如此。但是当我尝试使用ArrayList:
时Sub testArrayList()
Dim arr As Object
Set arr = CreateObject("System.Collections.ArrayList")
' Initialise the ArrayList, for instance by generating random values
Dim i As Long
Dim v As defaultProp
For i = 1 To 5
Set v = New defaultProp
arr.Add v 'no problem here
Next i
arr.Sort 'raises an error
End Sub
我收到错误
无法比较数组中的两个元素
那是怎么回事?这是我的方法中的一个缺陷 - 默认属性是不是ArrayList
?或者也许用于编写库的任何语言的比较运算符都不像VBA和Python使用的那样具有floopy-gloopy?有关更多内置排序算法的任何建议都是有用的!
答案 0 :(得分:4)
这与VBA比较运算符无关,ArrayList
是一个.NET类,所以当你使用它时,你就处于.NET世界。
arr.Add v 'no problem here
您正在添加defaultProp
类的实例;在类型上有一个默认属性并不重要,.NET不关心默认属性。如果您想对DefaultValue
值进行排序,然后执行arr.Add v.DefaultValue
或arr.Add (v)
- 那么您的ArrayList
将包含Single
类型的项目,它知道如何排序
为了使ArrayList.Sort
能够使用自定义类的实例,其项目需要实现IComparable
接口,System.Int32
就是这种情况(即Long
在VBA中),System.String
和其他所有原始.NET类型,我认为 VBA原语类型确实会通过.NET互操作正确编组 - 而不是自定义类。
尝试添加对 mscorlib.tlb 的引用,然后在defaultProp
类模块中指定此项(您无法实现在后期绑定库中定义的接口) :
Implements IComparable
然后实现界面 - 应该看起来像这样(使用codepane下拉菜单以确保获得正确的签名 - 不要只是复制粘贴此代码段:
Private Function IComparable_CompareTo(ByVal obj As Variant) As Long
Dim other As defaultProp
Set other = obj
' return Less than zero (-1) if this object
' is less than the object specified by the CompareTo method.
' return Zero (0) if this object is equal to the object
' specified by the CompareTo method.
' return Greater than zero (1) if this object is greater than
' the object specified by the CompareTo method.
End Function
现在您的自定义类实现了ArrayList.Sort
用于确定defaultProp
项与彼此之间关系的接口,我没有看到它失败的原因。
答案 1 :(得分:4)
ArrayList
并尝试Sort
它
我认为看看你是否可以在VBA类上实现IComparable
然后让ArrayList
使用IComparable
接口将对象与其他对象进行比较会更合乎逻辑但是你想要它进行比较,而不使用任何黑客攻击的默认属性。
答案 2 :(得分:2)
如果将DefaultValue添加到google.com
,它将起作用:
arr
显然Sub testArrayList()
'... code
For i = 1 To 5
Set v = New defaultProp
arr.Add v.DefaultValue
Next i
arr.Sort
End Sub
.Sort
的实现有点奇怪,不喜欢比较对象及其默认值(无法找到ArrayList
方法的实现)。虽然,这将完美无瑕地运作:
Sort()
这是一种可能的排序实现,可以按预期用于For i = 1 To 5
Set v = New defaultProp
arr.Add v
Next i
Debug.Print arr(1) > arr(2)
对象。但是,它不是arr
库的一部分:
ArrayList
但排序还可以: