在VBScript中将项目添加到数组

Posted

技术标签:

【中文标题】在VBScript中将项目添加到数组【英文标题】:Add item to array in VBScript 【发布时间】:2011-01-05 14:40:27 【问题描述】:

如何在 VBScript 中将项目添加到现有数组中?

有没有 VBScript 等价于 javascript 中的 push 功能?

myArray 包含三个项目,“Apples”、“Oranges”和“Bananas”,我想在数组末尾添加“Watermelons”。

【问题讨论】:

【参考方案1】:

数组在 VBScript 中不是很动态。您必须使用 ReDim Preserve 语句来扩展现有数组,以便它可以容纳额外的项目:

ReDim Preserve yourArray(UBound(yourArray) + 1)
yourArray(UBound(yourArray)) = "Watermelons"

【讨论】:

请注意,Redim Preserve 每次使用时都会复制整个数组。换句话说,它在 big-O 表示法中具有 n**2 复杂度。 @user,复制整个数组的复杂度是线性的(O(n)),而不是二次的(O(n²))。 当然制作一份是线性的。我在这里的意思是以这种方式构建数组。填充 100k 阵列与使用 Redim Preserve 填充 200k 阵列肯定需要 4 倍的时间,而不是 2 倍)。这不仅仅是理论,你可以自己尝试一下,你会看到的。我通常做的(实现起来很简单,但意味着巨大的性能提升)是每次索引将要高于上限时将上限增加 1.1 倍。 我有一个类型不匹配:'UBound' 在给出 ReDim Preserve 语句时(在使用 Dim 初始化之后)... @Pixie,对,看起来 Dim 创建了一个没有大小的数组,而不是一个实际的动态数组(documentation 对此不清楚,并说 dynamic地方)。 UBound() 不能应用于此类数组。结论:在任何地方使用ReDim,你会没事的。【参考方案2】:

为了您的复制和粘贴方便

' add item to array
Function AddItem(arr, val)
    ReDim Preserve arr(UBound(arr) + 1)
    arr(UBound(arr)) = val
    AddItem = arr
End Function

这样使用

a = Array()
a = AddItem(a, 5)
a = AddItem(a, "foo")

【讨论】:

【参考方案3】:

有几种方法,不包括自定义 COM 或 ActiveX 对象

    重新调整保留 字典对象,可以有字符串键并搜索它们 ArrayList .Net Framework 类,它有很多方法,包括: 排序(正向、反向、自定义)、插入、删除、 binarysearch、equals、toArray 和 toString

通过下面的代码,我发现 Redim Preserve 在 54000 以下最快,Dictionary 在 54000 到 690000 之间最快,Array List 在 690000 以上最快。由于排序和数组转换,我倾向于使用 ArrayList 进行推送.

user326639 提供了 FastArray,几乎是最快的。

字典对于搜索值和返回索引(即字段名称)或分组和聚合(直方图、分组和添加、分组和连接字符串、分组和推送子数组)很有用。对键进行分组时,设置比较模式以区分大小写,并在“添加”之前检查“存在”属性。

Redim 不会为一个数组节省太多时间,但它对于数组字典很有用。

'pushtest.vbs
imax = 10000
value = "Testvalue"
s = imax & " of """ & value & """" 

t0 = timer 'ArrayList Method
Set o = CreateObject("System.Collections.ArrayList")
For i = 0 To imax
  o.Add value
Next
s = s & "[AList " & FormatNumber(timer - t0, 3, -1) & "]"
Set o = Nothing

t0 = timer 'ReDim Preserve Method
a = array()
For i = 0 To imax
  ReDim Preserve a(UBound(a) + 1)
  a(UBound(a)) = value
Next
s = s & "[ReDim " & FormatNumber(timer - t0, 3, -1) & "]"
Set a = Nothing

t0 = timer 'Dictionary Method
Set o = CreateObject("Scripting.Dictionary")
For i = 0 To imax
  o.Add i, value
Next
s = s & "[Dictionary " & FormatNumber(timer - t0, 3, -1) & "]"
Set o = Nothing

t0 = timer 'Standard array
Redim a(imax)
For i = 0 To imax
  a(i) = value
Next
s = s & "[Array " & FormatNumber(timer - t0, 3, -1) & "]" & vbCRLF
Set a = Nothing

t0 = timer 'Fast array
a = array()
For i = 0 To imax
 ub = UBound(a)
 If i>ub Then ReDim Preserve a(Int((ub+10)*1.1))
 a(i) = value
Next
ReDim Preserve a(i-1)
s = s & "[FastArr " & FormatNumber(timer - t0, 3, -1) & "]"
Set a = Nothing

MsgBox s

'  10000 of "Testvalue" [ArrayList 0.156][Redim 0.016][Dictionary 0.031][Array 0.016][FastArr 0.016]
'  54000 of "Testvalue" [ArrayList 0.734][Redim 0.672][Dictionary 0.203][Array 0.063][FastArr 0.109]
' 240000 of "Testvalue" [ArrayList 3.172][Redim 5.891][Dictionary 1.453][Array 0.203][FastArr 0.484]
' 690000 of "Testvalue" [ArrayList 9.078][Redim 44.785][Dictionary 8.750][Array 0.609][FastArr 1.406]
'1000000 of "Testvalue" [ArrayList 13.191][Redim 92.863][Dictionary 18.047][Array 0.859][FastArr 2.031]

【讨论】:

我建议你添加这段代码: t0 = timer 'Fast array a = array() For i = 0 To imax ub = UBound(a) If i>ub Then ReDim Preserve a( Int ((ub+10)*1.1)) a(i) = value Next ReDim Preserve a(i-1) s = s & "[FastArr " & FormatNumber(timer - t0, 3, -1) & "]"设置 a = 无 谢谢!我永远也想不出那个 @mgr326639 最后的ReDim Preserve a(i-1)怎么了? @sirdank 最后的Redim Preserve 用于将数组的上限设置为正确的值。换句话说,摆脱未使用的保留空间。现在您可以使用For each itm in arr,迭代将停止在应有的位置;在您的数组中的最后一项。【参考方案4】:

从上面对 FastArray 进行轻微更改:

'pushtest.vbs
imax = 10000000
value = "Testvalue"
s = imax & " of """ & value & """" 

t0 = timer 'Fast array
a = array()
ub = UBound(a)
For i = 0 To imax
 If i>ub Then 
    ReDim Preserve a(Int((ub+10)*1.1))
    ub = UBound(a)
 End If
 a(i) = value
Next
ReDim Preserve a(i-1)
s = s & "[FastArr " & FormatNumber(timer - t0, 3, -1) & "]"

MsgBox s

如果我们确切地知道它何时发生变化,那么在 for 的每个循环中检查 UBound(a) 是没有意义的。

我已对其进行了更改,使其在 for 开始之前检查 UBound(a),然后仅在每次调用 ReDim 时检查

在我的电脑上,旧方法需要 7.52 秒才能达到 1000 万的 imax。

新方法耗时 5.29 秒,imax 也达到 1000 万次,这意味着性能提升超过 20%(对于 1000 万次尝试,显然这个百分比与尝试次数有直接关系)

【讨论】:

【参考方案5】:

基于Charles Clayton's answer,但略有简化...

' add item to array
Sub ArrayAdd(arr, val)
    ReDim Preserve arr(UBound(arr) + 1)
    arr(UBound(arr)) = val
End Sub

这样使用

a = Array()
AddItem(a, 5)
AddItem(a, "foo")

【讨论】:

【参考方案6】:

这有点晚了,但无论如何,这也有点棘手

 dim arrr 
  arr= array ("Apples", "Oranges", "Bananas")
 dim temp_var 
 temp_var = join (arr , "||") ' some character which will not occur is regular strings 
 if len(temp_var) > 0 then 
  temp_var = temp_var&"||Watermelons" 
end if 
arr  = split(temp_var , "||") ' here you got new elemet in array ' 
for each x in arr
response.write(x & "<br />")
next' 

查看并告诉我这是否可行 或者最初您将所有数据保存在字符串中,然后拆分为数组

【讨论】:

【参考方案7】:

不是答案为什么'tricky'不好

>> a = Array(1)
>> a = Split(Join(a, "||") & "||2", "||")
>> WScript.Echo a(0) + a(1)
>>
12

【讨论】:

以上是关于在VBScript中将项目添加到数组的主要内容,如果未能解决你的问题,请参考以下文章

如何在VBScript中将循环结果存储到数组中?

使用 VBScript 将代码回显到文件中

在 Promise 中将项目添加到数组时遇到问题

在 Swift 中将项目添加到 Firebase 数组而不首先观察数组

如何在 jQuery 中将项目添加到数组中?

vbscript 添加到字符串数组