代码之家  ›  专栏  ›  技术社区  ›  Fredrik

vba-创建字符串/哈希的唯一ID

  •  1
  • Fredrik  · 技术社区  · 6 年前

    首先,我很抱歉没有显示任何代码,但现在我需要一些关于如何提取字符串的唯一ID的指导。

    所以我有一些关于如何组织数据的问题。假设数据是经过组织的,因此每个dataid都有其唯一的名称。我将数据收集到保存它的数组中。

    我现在遇到的问题是,我想要一种简单的方法来搜索这些 nameid 。假设数据要大得多,并且包含超过几百种不同的名称ID的独特组合。因此,我认为搜索ID本身并不合适,我正在考虑创建一个哈希,我可以使用算法来搜索数组。我想这样做是因为稍后我将比较名称并将值添加到各自的名称ID中。请记住, nameid 在大多数情况下具有相同的结构,但最终会有一个新的名称,如 total_air 可以实现,然后我需要在数组中搜索以获得正确的值。

    更新时间:

    从Excel收集数据的代码示例:

    对于wb.工作表中的每个目标表 带目标表 '填充数组 xdata(0)=应用程序。转置(范围(单元格(1,1),单元格(1,1)。结束(xldown))。值2) cnt=ubound(扩展数据(0)) 以结尾 调用ddata.init(cnt) '填充ObjectArray ddata.setNameArray=扩展数据(0) 下一个目标表

    类型对象:

    private index as integer
    作为字符串的专用ID
    private nameid()作为变量
    私有数据()作为变量
    作为整数的专用CNT
    
    public sub init(值为整数)
    索引=0
    cnt=值
    ID=“”
    redim名称ID(0到cnt)
    redim数据(0到cnt)
    末端接头
    
    属性let setid(值为字符串)
    ID=值
    结束属性
    
    属性let setnamearray(值为variant)
    name id=值
    结束属性
    

    继承数据结构的dlist:。

    private xarray()as datastruct
    private listind为整数
    
    public sub init(cnt为整数)
    Redim Xarray(1至CNT)
    dim num为整数
    对于num=1到cnt
    set xarray(num)=new datastruct
    下一个
    列表标识=1
    末端接头
    属性let addarray(值为datastruct)
    设置xarray(listind)=value
    listind=listind+1
    结束属性
    

    孔列表的外观:

    .

    所以我有一些关于如何组织数据的问题。假设数据是经过组织的,因此每个dataid都有其唯一的名称。我将数据收集到保存它的数组中。

    我现在的问题是我想要一个简单的方法来搜索这些nameID.假设数据要大得多,并且包含超过几百种不同的名称ID的独特组合。因此,我认为搜索ID本身并不合适,我正在考虑创建一个哈希,我可以使用算法来搜索数组。我想这样做是因为稍后我将比较名称并将值添加到各自的名称ID中。记住名称ID大多数时候会有相同的结构,但最终会有一个新的名字total_air可以实现,然后我需要在数组中搜索以获得正确的值。

    更新时间:

    从Excel收集数据的代码示例:

    For Each targetSheet In wb.Worksheets
        With targetSheet
        'Populate the array
            xData(0) = Application.Transpose(Range(Cells(1, 1), Cells(1, 1).End(xlDown)).Value2)
            cnt = UBound(xData(0))
        End With
        Call dData.init(cnt)
        'Populate the objectarray
        dData.setNameArray = xData(0)
    Next targetSheet
    

    类型对象:

    Private index As Integer
    Private id As String
    Private nameID() As Variant
    Private data() As Variant
    Private cnt As Integer
    
    Public Sub init(value As Integer)
        index = 0
        cnt = value
        id = ""
        ReDim nameID(0 To cnt)
        ReDim data(0 To cnt)
    End Sub
    
    Property Let setID(value As String)
        id = value
    End Property
    
    Property Let setNameArray(value As Variant)
        nameID = value
    End Property
    

    继承数据结构的数据列表:

    Private xArray() As dataStruct
    Private listInd As Integer
    
    Public Sub init(cnt As Integer)
        ReDim xArray(1 To cnt)
        Dim num As Integer
        For num = 1 To cnt
            Set xArray(num) = New dataStruct
        Next
        listInd = 1
    End Sub
    Property Let addArray(value As dataStruct)
        Set xArray(listInd) = value
        listInd = listInd + 1
    End Property
    

    孔列表的外观:

    1 回复  |  直到 6 年前
        1
  •  1
  •   FunThomas    6 年前

    我强烈主张使用字典。它不仅更快地找到一个项目(我假设它是通过某种散列实现的),而且在添加或删除项目时有很大的优势。

    当您有一个数组并且想要添加一个项时,您要么总是使用 redim preserve 这是非常昂贵的,或者您定义的数组比最初需要的要大,并且总是必须保留实际使用了多少项的信息。从数组中删除一个项是相当复杂的。

    不能将类型化变量作为项值添加到字典中,但可以添加对象。所以不是你的 Type 定义,创建一个简单的 class 模块,只包含这些行(当然,您可以使用属性、getter和setter创建类,但这与本例无关)

    Public id As Long
    Public name As String
    Public value As Long
    

    那么,处理字典就相当简单了(请注意,您必须添加对 Microsoft脚本运行时

    Option Explicit
    
    Dim myList As New Dictionary
    
    Sub AddItemValues(id As Long, name As String, value As Long)
        Dim item As New clsMyData
        With item
            .id = id
            .name = name
            .value = value
        End With
        Call AddItem(item)
    End Sub
    
    Sub AddItem(item As clsMyData)
        If myList.Exists(item.id) Then
            set myList(item.id) = item
        Else
            Call myList.Add(item.id, item)
        End If
    End Sub
    
    Function SearchItem(id As Long) As clsMyData
        If myList.Exists(id) Then
            Set SearchItem = myList(id)
        Else
            Set SearchItem = Nothing
        End If
    End Function
    
    Function SearchName(name As String) As clsMyData
        Dim item As Variant
        For Each item In myList.Items
            If item.name = name Then
                Set SearchName = item
                Exit Function
            End If
        Next item
        Set SearchName = Nothing
    End Function
    

    只要你处理身份证,字典就会为你做所有的工作。只有当你搜索 name ,您必须循环字典的所有项,这与循环数组一样简单。

    一些测试(当然,您应该添加一些错误处理)

    Sub test()
        Call AddItemValues(32, "input_air", 0)
        Call AddItemValues(45, "air_Procent", 99)
        Call AddItemValues(89, "output_air", 34)
    
        Debug.Print SearchItem(45).name
        Debug.Print SearchName("output_air").value
    
        ' Change value of output_air
        Call AddItemValues(89, "output_air", 1234)
        Debug.Print SearchName("output_air").value
    End Sub