【问题标题】:Joining two arrays in vba?在vba中加入两个数组?
【发布时间】:2019-05-12 15:30:56
【问题描述】:

如何将这些数组与(2, 4, 5, 3, 7, 6) 的结果结合起来?

array1 = Array(4,5,3,7,6)

array2 = Array(2)

【问题讨论】:

  • 创建第三个数组,该数组的大小为两个数组组合的大小,然后循环遍历每个数组,逐个添加项目。
  • 仅供参考,为@ScottCraner 的评论添加了一个替代方法,如何使用Application.Index() 函数的高级可能性组合两个一维数组:-)

标签: arrays excel vba


【解决方案1】:

您可能会 Join() 并连接您的两个数组,然后 Split() 将结果返回到一个新数组:

array3 = Split(Join(array2, ",") & "," & Join(array1, ","), ",")

解释:
Join() 将返回一个字符串,其中数组中的每个元素(第一个参数)由","(第二个参数)分隔。我们用一个逗号连接这两个连接的数组,得到一个像2,4,5,3,7,6 这样的字符串。然后我们使用Split() 将该字符串转回一个数组,告诉Split() 分隔符是逗号","

【讨论】:

  • 一个警告是返回将是一个字符串,因此在检索值时可能需要对其进行一些其他工作。
  • Split() 的返回将是一个数组,但是是的......JOIN() 的返回将是一个字符串,如果一个元素包含正在使用的分隔符,那么返回的数组Split() 将是意大利面条。
  • Split 的返回将是一个字符串数组。
  • 啊! @ScottCraner 这是一个很好的警告!这完全是 hacky,但你知道我喜欢一个好的 hacky one-liner。
  • FYI "You know I love a good hacky one-liner." - 添加了另一个解决方案来“连接两个数组”,使用 Application.Index() 作为单线并保持数组值的原始类型(因为 Index() 导致基于 1 的结果,我需要进一步 ReDimming 回到从零开始的数组以保持原始设置)。
【解决方案2】:

您可以使用数组列表。如果需要,这也提供了一种简单的排序方式。

Option Explicit
Public Sub test()
    Dim list1 As Object, list2 As Object

    Set list1 = CreateObject("System.Collections.Arraylist")
    Set list2 = CreateObject("System.Collections.Arraylist")
    list1.Add 4
    list1.Add 5
    list1.Add 3
    list1.Add 7
    list1.Add 6
    list2.Add 2
    list1.addRange list2
    list1.Sort
End Sub

【讨论】:

  • FYI 添加了通过 arrayLists 来“连接两个数组”的替代方法。 :+)
  • 出于兴趣:是否有与Join() 相当的功能可以应用于arrayLists,例如Debug.Print Join(list1, "|") 对象将导致错误 13 类型不匹配。
  • @T.M.是的,你可以 > Join(list1.ToArray,"|") =)
【解决方案3】:

连接两个数组

作为 Scott Craner 提出的正确可行方法的替代方法

创建第三个数组,它的大小为两个数组组合的大小, 然后循环遍历每个数组,逐个添加项目。

...我演示了一种方法

  • 通过循环插入第二个数组的元素 到一个主数组中,而
  • 主数组仅由一个一个内衬通过Application.Index()重组

由于此函数会将结果更改为从 1 开始的数组,因此我将数组重新调整为从零开始的数组。此外,我在 VBE 的即时窗口中添加了一个可选显示,结果为 2|4|5|3|7|6 值:

第一步:使用与 OP 中相同的数组值的简单演示(插入 1 个元素)

Sub SimpleDemo()
'[0]declare and assign zero-based 1-dimensioned arrays
    Dim main, newTop
    main = Array(4, 5, 3, 7, 6)
    newTop = Array(2)              ' only one element in a first step
'[1]transform main array by inserting(/i.e. repeating) "another" 1st element
    main = Application.Index(main, Array(1, 1, 2, 3, 4, 5)) ' changes to 1-based 1-dim array
    ReDim Preserve main(0 To UBound(main) - 1)              ' back to zero-based 1-dim array
'[2]overwrite new first element by the 1st(only) element of newTop
    main(0) = newTop(0)
'[3](optional) display in VBE's Immediate Window: main(0 To 5) ~> 2|4|5|3|7|6
    Debug.Print "main(" & LBound(main) & " To " & UBound(main) & ") ~> " & _
                Join(main, "|")
End Sub

第二步:使用AddElem 过程的更通用的方法

上面的演示只插入了一个一个元素。因此我编写了一个AddElem 过程和一个帮助函数addedElems() 以允许插入更多元素。假设所有 1-dim 数组都是从零开始的,就像在原始帖子中一样;顺便说一句,可以很容易地适应:-)

Sub AddElem(main, newTop)
' Purp. : add/insert other array element(s) on top of zero-based main array
' Author: https://stackoverflow.com/users/6460297/t-m
' Date  : 2020-02-05
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' a)insert newTop element(s) on top of main array
    main = Application.Index(main, addedElems(main, newTop)) ' changes temporarily to 1-based mainay!
' b)make main array zero-based again (optional)
    ReDim Preserve main(0 To UBound(main) - 1)
' c)overwrite inserted starting element(s) by the newTop element(s)
    Dim i&: For i = 0 To UBound(newTop): main(i) = newTop(i): Next i
End Sub

帮助功能addedElems()

Function addedElems(main, newTop) As Variant()
'Note : help function called by AddElem()
'Purp.: return ordinal element counters of combined arrays
    Dim i&, n&: n = UBound(main) + UBound(newTop) + 1
    ReDim tmp(0 To n)
    For i = 0 To UBound(newTop): tmp(i) = i: Next i
    For i = i To n: tmp(i) = i - UBound(newTop): Next i
    addedElems = tmp        ' return combined elem counters,  e.g. Array(1,2, 1,2,3,4,5)
End Function

调用示例

我稍微改变了 OP 的第二个数组的值(Array(2) ~>Array(20,21) 来演示更多元素的插入,因此 产生一个合并的Array(20,21,2,4,5,3,7,6)

Sub ExampleCall()
'[0]declare and assign zero-based 1-dimensional arrays
    Dim main, newTop
    main = Array(4, 5, 3, 7, 6)
    newTop = Array(20, 21)
'[1]Add/Insert newTop on top of main array
    AddElem main:=main, newTop:=newTop     ' or simply: AddElem main, newTop

'[2](optional) display in VBE's Immediate Window: ~~> main(0 To 6) ...20|21|4|5|3|7|6
    Debug.Print "main(" & LBound(main) & " To " & UBound(main) & ") ..." & _
                Join(main, "|")
End Sub

相关链接

同样,您可以在Insert first column in datafield array without loops or API calls 研究应用于二维数组的Application.Index() 函数的一些特性

【讨论】:

  • 赞成彻底解释,顺便说一句,看到你最近对Application.Methods 感兴趣 =)
【解决方案4】:

聚会迟到了,但我还要加两分钱

您可以简单地将两个数组之一复制 到一个新数组中。然后Redim Preserve 是两个原始数组的大小,然后循环第一个数组。以下代码是基本代码,但无需转换任何数据类型即可快速完成工作:

Sub Test()

Dim arr1 As Variant: arr1 = Array(4, 5, 3, 7, 6)
Dim arr2 As Variant: arr2 = Array(2)
Dim arr3 As Variant: arr3 = arr2

ReDim Preserve arr3(UBound(arr1) + Ubound(arr2) + 1)
For x = (UBound(arr3) - UBound(arr1)) To UBound(arr3)
    arr3(x) = arr1(x - UBound(arr2) - 1)
Next x

End Sub

使用一些Type 转换来演示不同Data Type 的返回:

Sub Test()

Dim arr1 As Variant: arr1 = Array(CDbl(4), CLng(5), CStr(3), CDate(7), CCur(6))
Dim arr2 As Variant: arr2 = Array(2)
Dim arr3 As Variant: arr3 = arr2

ReDim Preserve arr3(UBound(arr1) + Ubound(arr2) + 1)
For x = (UBound(arr3) - UBound(arr1)) To UBound(arr3)
    arr3(x) = arr1(x - UBound(arr2) - 1)
Next x

End Sub

【讨论】:

  • 很有帮助的另一种很好的方法展示了相同的想法,而不是循环遍历 each 数组,逐个添加项目:+)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
  • 2019-12-01
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多