2017-12-12 1 views
1

TL에 의한 클래스의 그룹, DR :정렬 기본 속성

알고리즘을 선별 라이브러리에 클래스 모음/목록을 통과하고, 바람직하게 (이 정렬 된 목록을 반환 얻을 방법이 있나요 명명 된/기본 클래스 속성)?

저는 최근에 일부 파이썬을 배우 았으며 어떤 반복 가능한 것을 정렬 할 수있는 Sorted() 함수에 깊은 인상을 받았습니다. 숫자의 경우 이것은 간단하지만 클래스의 경우 비교 방법 like this을 할당 할 수 있습니다. 이 메서드는 비교 연산자에게 클래스의 두 인스턴스를 비교하는 방법을 알려줍니다. 그 중에서도 내장 된 정렬 알고리즘을 사용하여 클래스 모음을 정렬 할 수 있습니다.

VBA에서 나는 이것을 반증하는 데 반 성공했습니다. 클래스 'default memberAttribute을 설정하면 클래스에 직접 비교 연산자 (<, =, >= 등)를 사용할 수 있습니다. 이 클래스의

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을 더함)

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가 아닌가? 시도하는 내장 된 정렬 알고리즘에 대한 제안도 유용 할 것입니다! 당신이 arr에의 DefaultValue를 추가하는 경우

답변

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 위해서는

는, 해당 항목은 System.Int32 (VBA에서 즉 Long), System.String 및 다른 모든 기본 .NET 유형의 경우입니다 IComparable 인터페이스를 구현해야하고, I 생각하면 VBA 기본 유형은 실제로 .NET interop을 통해 올바르게 정렬되지만 사용자 정의 클래스는 사용할 수 없습니다.

시도 에서 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 항목이 서로 관련되는 방식을 결정할 수있게되었으므로 실패 할 이유는 없습니다.

2

이 작동합니다 :

Sub testArrayList() 
    '... code 
    For i = 1 To 5 
     Set v = New defaultProp 
     arr.Add v.DefaultValue 
    Next i 
    arr.Sort   
End Sub 

분명히 ArrayList.Sort의 구현이 조금 이상하고 비교하는 객체와 기본 값을 (구현을 찾을 수 없습니다 좋아하지 않는다 Sort() 방법의). 이 완벽하게 작동합니다,하지만 :

For i = 1 To 5 
    Set v = New defaultProp 
    arr.Add v 
Next i  
Debug.Print arr(1) > arr(2) 

이 예상대로 arr 개체에 대한 작업을 할 정렬의 가능한 구현이다.그러나, ArrayList 라이브러리의 일부가 아닌 :

Public Function varBubbleSort(varTempArray As Object) As Object 

    Dim varTemp     As Object 
    Dim lngCounter    As Long 
    Dim blnNoExchanges   As Boolean 

    Do 
     blnNoExchanges = True 
     For lngCounter = 0 To varTempArray.Count - 2 
      If varTempArray(lngCounter) > varTempArray(lngCounter + 1) Then 
       blnNoExchanges = False 
       Set varTemp = varTempArray(lngCounter) 
       varTempArray(lngCounter) = varTempArray(lngCounter + 1) 
       varTempArray(lngCounter + 1) = varTemp 
      End If 
     Next lngCounter 

    Loop While Not (blnNoExchanges) 
    Set varBubbleSort = varTempArray 

    On Error GoTo 0 
    Exit Function 

End Function 

그러나 정렬 괜찮 :

enter image description here

+1

아, 그렇지만 클래스가 아닌 값 배열을 가지고 있습니다. 어떤 값으로 클래스 목록을 정렬하고 싶지만 실제적으로 전체 클래스 객체를 – Greedo

+0

@Greedo 주위로 이동하십시오. 편집을 참조하십시오. – Vityata

+0

그래서 비교 연산자는 클래스가 ArrayList (두 번째 코드 비트)에 추가 될 때 작동하지만 직접 정렬하지 않아도됩니까? 해결 방법에 대한 아이디어는 개체의 기본 값이 아니기 때문에 기본값으로 설정해야합니다 (물론 후자를 이전 개체로 매핑 할 수 있지만 라이브러리 정렬을 사용하지 않는 것이 좋습니다) – Greedo

4

IMO, 당신은 경계를 넘어 물건을 섞어 악용하고 있습니다. VBA의 기본 속성 (일반적으로 나쁜 습관으로 인식되는 것)을 사용하는 경우 .NET의 ArrayList을 사용하고 Sort을 시도합니다.

나는 당신이 VBA 클래스에 IComparable를 구현하고 모든 기본값을 사용하지 않고 ArrayList 당신이, 그것은 비교할 그러나하여 다른에 대한 객체를 비교하는 IComparable 인터페이스를 사용하도록 할 수 있는지 확인하기 위해 훨씬 더 논리적 일 것 같아 속성이 해킹되었습니다.

+0

매트의 머그컵이 지적했듯이, 나는 생각하지 않는다. 'IComparable'을 구현하지 않고 ArrayList로 정렬을 구현하는 방법이 있습니다 (기본 속성은 도움이되지 않습니다!) 그것은 가능한 접근 이었지만 다른 옵션이 있음을 알았습니다. – Greedo