数据处理工程中经常用到去重和取唯一值,或者取几组数据的交集与并集,其实这两类问题的求解思路是相同的。字典对象中的元素具备唯一性,因此经常被用来处理此类问题。
假设有如下数据集合,对于B列和C列数据需要求取交集和并集等数据集合。
示例代码如下:
'Option Explicit
Sub LoadData()
Dim aData, aRes, lst, iRow, iCol, iKeyCol
Dim bDic, cDic, bcDic, bNotcDic, cNotbDic, allDic
Const COLUMNS_QTY = 3
With ActiveSheet
iKeyCol = 1
lst = .Cells(.Rows.Count, iKeyCol).End(xlUp).Row
aData = .Cells(1, iKeyCol).Resize(lst, COLUMNS_QTY).Value
Set bDic = CreateObject("Scripting.Dictionary")
Set cDic = CreateObject("Scripting.Dictionary")
Set bcDic = CreateObject("Scripting.Dictionary")
Set bNotcDic = CreateObject("Scripting.Dictionary")
Set cNotbDic = CreateObject("Scripting.Dictionary")
Set allDic = CreateObject("Scripting.Dictionary")
For iRow = 1 To UBound(aData, 1)
keyb = aData(iRow, 2)
If Not bDic.exists(keyb) Then bDic(keyb) = keyb
keyc = aData(iRow, 3)
If Not cDic.exists(keyc) Then cDic(keyc) = keyc
Next iRow
For Each b In bDic.keys
If cDic.exists(b) Then
bcDic(b) = b
Else
bNotcDic(b) = b
End If
allDic(b) = b
Next b
For Each c In cDic.keys
If Not bDic.exists(c) Then
cNotbDic(c) = c
allDic(c) = c
End If
Next c
Range("E:H").Clear
Range("E1:H1").Value = Array("B和C公有", "B独有", "C独有", "B和C并集")
Range("E2").Resize(bcDic.Count, 1).Value = Application.Transpose(bcDic.items())
Range("F2").Resize(bNotcDic.Count, 1).Value = Application.Transpose(bNotcDic.items())
Range("G2").Resize(cNotbDic.Count, 1).Value = Application.Transpose(cNotbDic.items())
Range("H2").Resize(allDic.Count, 1).Value = Application.Transpose(allDic.items())
End With
Set bDic = Nothing
Set cDic = Nothing
Set bcDic = Nothing
Set bNotcDic = Nothing
Set cNotbDic = Nothing
Set allDic = Nothing
End Sub
【代码解析】
第8行代码指定用于定位最后数据行的数据列,示例代码中使用A列。
第9行代码使用End(xlUp)
定位最后一行数据所在行。
第10行代码将数据加载到数组中,便于后续处理。
第11行到第16行代码创建6个字典对象。
变量名称 | 用途 |
---|---|
bDic | B列数据唯一值 |
cDic | C列数据唯一值 |
bcDic | B列和C列公用有数据,即交集 |
bNotcDic | B列不存在于C列中的数据 |
cNotbDic | C列不存在于B列中的数据 |
allDic | B列和C列数据的合集,即并集 |
第24行代码和第32行代码使用字典对象的exists属性
判断指定关键字是否已经存在于字典的KEYS
中。
第23行到26行代码通过循环判断,获取四个字典对象。
第38行代码写入结果标题行。
第39行到第42行代码分别将数据写入指定列。
第44行到第49行代码清空对象变量,释放系统资源。
示例代码运行结果如下。
使用字典对象获取数据唯一值与重复值的其他应用场景与此示例基本上是大同小异的,只需要做少量代码修改即可。