代码更新,并作了简单注释。- Dim sj$(), jg(), d, m&, n&, k&
- Sub kagawa()
- Dim i&, l&, r$
- tms = Timer
-
- sj0 = [a2].CurrentRegion
- n = 3
- m = UBound(sj0, 2) - 3
- Set d = CreateObject("Scripting.Dictionary") '设置字典便于统计相同组合
-
- ReDim sj$(1 To m) '定义数组存放 排序后的本行原始数据
- ReDim jg(65534, 2) '定义储存结果的数组jg
- k = 0 '字典统计关键词个数初始化
- For i = 2 To UBound(sj0)
- Call px(sj0, sj, i) '本行数据排序
- r = sj0(i, 1) & sj0(i, 2) '本行信息
- Call dgZH(r, "", 0, 1) '递归组合,并在组合过程中使用字典
- Next
-
- With [a2].Offset(, m + 4)
- .CurrentRegion.Offset(1) = ""
- .Resize(k, 3) = jg '输出结果到工作表
- .Resize(k, 3).Sort .Offset(0, 0), 2, , , , , , 2 '结果按出现次数倒排序
- .Resize(k, 3).Offset(15) = "" '仅保留前15个结果 (需要增减保留数时改Offset括号里的值即可)
- End With
- MsgBox Format(Timer - tms, "0.000s ") & k
- ' Erase jg
- End Sub
- Function px(sj0, sj$(), i&) '插入排序代码
- Dim j&, l&, t$
- sj(1) = Right("0" & sj0(i, 3), 2)
- For j = 2 To m
- t = Right("0" & sj0(i, j + 2), 2)
- For l = j To 2 Step -1
- If t < sj(l - 1) Then sj(l) = sj(l - 1) Else Exit For
- Next
- sj(l) = t
- Next
- End Function
- Sub dgZH(r$, s$, i&, t&) '递归组合代码
- Dim j&, s1$, s2$
- For j = i + 1 To m - n + t
- If t < n Then
- Call dgZH(r, s & sj(j), j, t + 1) '组合抽取数不足n时继续深层递归
- Else
- s1 = s & sj(j) '得到本次组合结果
- s2 = d(s1) '用字典检查本组合的序号
- If s2 = "" Then '如字典为空则新增一行记录,并写入基本信息
- k = k + 1: d(s1) = k: jg(k, 0) = 1: jg(k, 1) = Format(s1, "'00-00-00"): jg(k, 2) = "'" & r
- Else
- '否则如已重复则在结果数组jg中添加相关信息,
- '字典查询返回得到的s2内容即为该组合在结果数组中的序号位置
- jg(s2, 0) = jg(s2, 0) + 1 '出现次数+1
- jg(s2, 2) = jg(s2, 2) & " " & r '行信息合并加入
- End If
- End If
- Next
- End Sub
复制代码 我的代码整体还算比较简单易懂的。
|