几年前我有类似的要求。我不记得为什么,我不再有代码,但我记得算法。对我来说这是一次性练习,所以我想要一个简单的代码。我并不在乎效率。
我将假设一个基于数组,因为它使得一个稍微简单的解释。由于VBA支持基于一个数组,所以这应该是确定的,但如果这是您想要的,则可以轻松调整基于零的数组。
AllFields(1到NumFields)包含名称。
有一个循环:对于INX = 1到2^NumFields - 1
在循环内考虑INX与位的二进制数编号为1至NumFields。对于1到NumFields之间的每个N,如果N是1,那么在这个组合中包含AllFields(N)。
这个循环产生2^NumFields - 1个组合:
Names: A B C
Inx: 001 010 011 100 101 110 111
CombinationS: C B BC A A C AB ABC
与VBA越来越位N的值。
额外部分
对于具有每个人唯一的困难在执行我的算法时,我想我最好说明我会如何做到这一点。
由于我们尚未被告知名称中可能包含哪些字符,因此我已经填充了一组测试数据和一组令人讨厌的字段名称。
子程序GenerateCombinations完成业务。我是递归的粉丝,但我认为我的算法不够复杂,无法证明它在这种情况下的使用。我将结果返回到一个锯齿状的数组,我更喜欢串联。 GenerateCombinations的输出被输出到立即窗口以显示其输出。
Option Explicit
这个例程演示GenerateCombinations
Sub Test()
Dim InxComb As Integer
Dim InxResult As Integer
Dim TestData() As Variant
Dim Result() As Variant
TestData = Array("A A", "B,B", "C|C", "D;D", "E:E", "F.F", "G/G")
Call GenerateCombinations(TestData, Result)
For InxResult = 0 To UBound(Result)
Debug.Print Right(" " & InxResult + 1, 3) & " ";
For InxComb = 0 To UBound(Result(InxResult))
Debug.Print "[" & Result(InxResult)(InxComb) & "] ";
Next
Debug.Print
Next
End Sub
GenerateCombinations做业务。
Sub GenerateCombinations(ByRef AllFields() As Variant, _
ByRef Result() As Variant)
Dim InxResultCrnt As Integer
Dim InxField As Integer
Dim InxResult As Integer
Dim I As Integer
Dim NumFields As Integer
Dim Powers() As Integer
Dim ResultCrnt() As String
NumFields = UBound(AllFields) - LBound(AllFields) + 1
ReDim Result(0 To 2^NumFields - 2) ' one entry per combination
ReDim Powers(0 To NumFields - 1) ' one entry per field name
' Generate powers used for extracting bits from InxResult
For InxField = 0 To NumFields - 1
Powers(InxField) = 2^InxField
Next
For InxResult = 0 To 2^NumFields - 2
' Size ResultCrnt to the max number of fields per combination
' Build this loop's combination in ResultCrnt
ReDim ResultCrnt(0 To NumFields - 1)
InxResultCrnt = -1
For InxField = 0 To NumFields - 1
If ((InxResult + 1) And Powers(InxField)) <> 0 Then
' This field required in this combination
InxResultCrnt = InxResultCrnt + 1
ResultCrnt(InxResultCrnt) = AllFields(InxField)
End If
Next
' Discard unused trailing entries
ReDim Preserve ResultCrnt(0 To InxResultCrnt)
' Store this loop's combination in return array
Result(InxResult) = ResultCrnt
Next
End Sub
你想通过这样做达到什么目的?洞察一个问题试图达到的目标往往会导致实现这一目标的更好方式。 – cdeszaq 2012-01-06 15:40:00
我将它与会计数据库中的总帐一起使用,其中GL本身没有可用于隔离特定交易的事务标识符/唯一ID字段。所以我想要做的是找到最合适的字段组合来创建这样一个唯一的ID字段,而不必手动测试所有可能的组合。 – dmacp 2012-01-06 15:49:19
因此,您正在查找_current_数据指示为唯一的字段组合,而不是_domain_指示的唯一字段集合?这听起来像是一场灾难。如果你选择一组字段作为标识符,并且事实证明它不在路上,你可能会发现自己处于一个痛苦的世界。 – cdeszaq 2012-01-06 15:55:47