如何根据某个有序超集对子集进行排序?

时间:2018-10-26 19:08:29

标签: arrays vba sorting

假设我有一个未排序的字符串数组;我们将其称为集合A。此数组中的每个字符串还存在于较大的字符串数组中,即集合B,其中较大的数组以某种任意方式排序。

我要对A进行排序,使其:

对于A中的每个元素E,

  • A中所有其他元素都出现在B中的E之前,也出现在A中的E之前。
  • A的所有其他元素出现在B中的E之后也出现在B中的E之前

例如,假设集合B为:[牛,马,猪,鸡,山羊,狗]
假设未排序的集合A为:[马,狗,猪,牛]

排序后,集合A应该看起来像:[牛,马,猪,狗]

我最初对如何解决此问题的想法是建立一个新的集合,或在VBA中建立一个字符串数组:

  • 声明新数组C
  • 遍历B的元素
    • 如果B的元素存在于A中,则将元素追加到C

数组C现在由A中的所有元素组成,按照它们在B中出现的顺序

虽然我相当有信心这种方法行得通(尽管B远大于A,效率不高),但我想知道是否有人在考虑最佳做法的情况下对如何更有效地做到这一点有所建议,我希望在VBA中实现这一点,但是伪代码就足够了。谢谢! (抱歉,草率的格式;第一次在这里发布!)

1 个答案:

答案 0 :(得分:0)

因此,我一直在研究记录集而不是很多this month on my blog,所以我可以告诉你,您的用例适合使用ADO记录集。

在下面的代码中,您可以看到我们有一个主集合,然后可以过滤到一个子集。同样,在代码中,我们将快照快照以显示排序顺序。然后,我们在另一个字段上对主集进行排序,这将更改子集的排序,以及在第二个快照中可以看到的。

Option Explicit

'* Tools->References
'ADODB      Microsoft ActiveX Data Objects 6.1 Library  C:\Program Files (x86)\Common Files\System\ado\msado15.dll

Sub Test()

    Dim rstADO As ADODB.Recordset
    Dim fld As ADODB.Field

    Set rstADO = New ADODB.Recordset
    With rstADO
        .Fields.Append "Animal", adVarChar, 20
        .Fields.Append "BirthDay", adDate, FieldAttributeEnum.adFldKeyColumn
        .Fields.Append "ArrivalSequence", adInteger

        .CursorType = adOpenKeyset
        .CursorLocation = adUseClient
        .LockType = adLockPessimistic
        .Open

        .AddNew Array("Animal", "BirthDay", "ArrivalSequence"), Array("Cow", Now() - 200, 1)
        .AddNew Array("Animal", "BirthDay", "ArrivalSequence"), Array("Horse", Now() - 100, 2)
        .AddNew Array("Animal", "BirthDay", "ArrivalSequence"), Array("Pig", Now() - 150, 3)
        .AddNew Array("Animal", "BirthDay", "ArrivalSequence"), Array("Chicken", Now() - 120, 4)
        .AddNew Array("Animal", "BirthDay", "ArrivalSequence"), Array("Goat", Now() - 180, 5)
        .AddNew Array("Animal", "BirthDay", "ArrivalSequence"), Array("Dog", Now() - 140, 5)


        .Filter = "Animal='Cow' or Animal='Dog' or Animal='Pig'  or Animal='Horse'"

        Dim vSnap As Variant
        .MoveFirst
        vSnap = .GetRows

        Debug.Assert vSnap(0, 0) = "Cow"
        Debug.Assert vSnap(0, 1) = "Horse"
        Debug.Assert vSnap(0, 2) = "Pig"
        Debug.Assert vSnap(0, 3) = "Dog"


        '*
        '* Now sort according to birthday
        '*
        .Sort = "BirthDay"


        Dim vSnap2 As Variant
        .MoveFirst
        vSnap2 = .GetRows

        Debug.Assert vSnap2(0, 0) = "Cow"
        Debug.Assert vSnap2(0, 1) = "Pig"
        Debug.Assert vSnap2(0, 2) = "Dog"
        Debug.Assert vSnap2(0, 3) = "Horse"


    End With

End Sub

Excel Development Platform: VBA - Fabricate an ADO Recordset for Sorting and Filtering