【问题标题】:Can we reset For loop counter in VBScript?我们可以在 VBScript 中重置 For 循环计数器吗?
【发布时间】:2013-01-02 23:02:37
【问题描述】:

我有一个数组说:VMHArray = (12,22,34,4) 现在有另一个 Arraylist 对象说 ArrayListTaskDetails 将数据保存为 (12,55,44,4,12,22, 21,107,43,22,34) 现在我编写了以下代码,用于从 ArrayListTaskDetails 列表中删除 VMHArray 中不存在的项目。

代码

Dim Flag : Flag = true
Dim Counter
For IndexSearch = 0 To ArrayListTaskDetails.Count - 1 step 4

    Counter = 0
    Do while Flag

        If VMHArray(Counter) <> ArrayListTaskDetails (IndexSearch) Then

          ArrayListTaskDetails.RemoveRange IndexSearch, 4
          Flag = False

        End If
    Counter = Counter + 1
    Loop

Next

现在假设在IndexSearch = 0 找到一个匹配项,因此它将删除位置0,1,2,3 处的元素 - 非常好。但由于删除和使ArrayList 对象通过功能连续,其他元素将由4 向左移动。现在的问题是For Loop 已经增加了 4,所以它将从location 4 的下一次迭代开始。因此,现在数组列表中0 location 处的新元素永远无法测试与VMHArray 数组元素的相等性。我们可以在不丢失预期操作的情况下处理这种情况吗?或者无论如何我们可以将For Loop 计数器设置为其直接位置,在该位置找到最近的匹配项并删除了 4 个元素。

如果有任何问题理解问题,请告诉我!

编辑 Go to 不起作用

代码(根据@Ankit 的建议)

Option Explicit

Dim Flag : Flag = true
Dim Counter
Dim VMHArray : VMHArray = Array(12,22,34,4) 
Dim ArrayListTaskDetails : Set ArrayListTaskDetails = CreateObject("System.Collections.ArrayList")

    ArrayListTaskDetails.Add(45)
    ArrayListTaskDetails.Add(4)
    ArrayListTaskDetails.Add(22)
    ArrayListTaskDetails.Add(4)
    ArrayListTaskDetails.Add(45)
    ArrayListTaskDetails.Add(20)
    ArrayListTaskDetails.Add(12)
    ArrayListTaskDetails.Add(35)
    ArrayListTaskDetails.Add(34)

    Restart:
For IndexSearch = 0 To ArrayListTaskDetails.Count - 1 step 4

    Counter = 0
    Do while Flag

        If VMHArray(Counter) <> ArrayListTaskDetails (IndexSearch) Then

          ArrayListTaskDetails.RemoveRange IndexSearch, 4
          Goto Restart
          Flag = False

        End If
    Counter = Counter + 1
    Loop

Next

MsgBox(Join(ArrayListTaskDetails.ToArray()),"$")

谢谢,

【问题讨论】:

  • 你试过exit forfor还是试试this to exit while loop
  • @bonCodigo 如果我使用了exit for,那么如何检查其余元素?
  • 只需将循环从最后一个元素迭代到第一个元素,例如For IndexSearch = ArrayListTaskDetails.Count - 1 To 0 step -4。这也将避免对已检查的元素进行不必要的循环。
  • @AutomatedChaos - 向后循环是正确的,但你的起始位置是错误的(应该是 .Count - 4)
  • @CodeLover 您的 Join 语句的括号放置不正确,让 ,"$" 属于 MsgBox(Join 的第二个参数是可选的,这就是为什么您不会收到错误该声明)。如果要使用括号,则 MsgBox 需要为called,否则请去掉它们。现在,VBScript 引擎将"$" 视为消息框的第二个(可选)参数,并向您发出警告。

标签: excel vbscript vba


【解决方案1】:

解决问题的两个思路:

  1. 使用字典检查要保留的项目
  2. 向后循环

在代码中:

Option Explicit

Dim alSrc : Set alSrc = CreateObject("System.Collections.ArrayList")
Dim sE
For Each sE In Split("a x x x b x x x c x x x d x x x e x x x f x x x a x x x")
    alSrc.Add sE
Next
WScript.Echo "alSrc:", Join(alSrc.ToArray(), ".")
Dim aKeep   : aKeep       = Split("a d")
WScript.Echo "aKeep:", Join(aKeep, ".")
Dim dicKeep : Set dicKeep = CreateObject("Scripting.Dictionary")
For Each sE In aKeep
    dicKeep(sE) = 0
Next
WScript.Echo "dicKeep:", Join(dicKeep.Keys(), ".")
Dim nI
For nI = alSrc.Count - 4 To 0 Step -4
    sE = alSrc(nI)
    If Not dicKeep.Exists(sE) Then
       alSrc.RemoveRange nI, 4
    End If
    WScript.Echo sE, nI, Join(alSrc.ToArray(), ".")
Next
WScript.Echo "alSrc:", Join(alSrc.ToArray(), ".")

输出:

alSrc: a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.e.x.x.x.f.x.x.x.a.x.x.x
aKeep: a.d
dicKeep: a.d
a 24 a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.e.x.x.x.f.x.x.x.a.x.x.x
f 20 a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.e.x.x.x.a.x.x.x
e 16 a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.a.x.x.x
d 12 a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.a.x.x.x
c 8 a.x.x.x.b.x.x.x.d.x.x.x.a.x.x.x
b 4 a.x.x.x.d.x.x.x.a.x.x.x
a 0 a.x.x.x.d.x.x.x.a.x.x.x
alSrc: a.x.x.x.d.x.x.x.a.x.x.x

关于 .Count - ? 的奥秘:

1 2 3 4 5 6 7 8 - Count 1 - 8
0 1 2 3 4 5 6 7 - Idx   0 - 7
A x x x B x x x - Count (8) - Step (4) = Pos to check (4)
                  Count (8) - Step + 1 (5) = Not the pos to check (3)

【讨论】:

  • 你能给我一个关于帖子的提示吗?Post。我在那里试过,但看的是一个班轮,我知道这是可能的,所以请你帮忙!请
  • 为什么 .Count-4 不是 .Count-5。由于 Count 给了我们元素的总数,并且为了访问我们总是使用 ArrayList(Count-1) 的元素。如果我错了,请纠正我!
  • 感谢您的澄清!!爱你的知识!
  • 你能帮我完成上面提到的帖子吗?
【解决方案2】:

重置For loop counter 意味着你有点不让它iterate。你必须非常小心不要碰到infinite loop。坦率地说,没有阅读你的大文本。但是查看您的代码和标题,请尝试以下操作:

For IndexSearch = 0 To ArrayListTaskDetails.Count - 1 step 4
    Counter = 0
    Do while Flag
       If VMHArray(Counter) = ArrayListTaskDetails (IndexSearch) Then
          ArrayListTaskDetails.RemoveRange IndexSearch, 4
          Flag = False
          If IndexSearch >= 4 then 
            IndexSearch = IndexSearch - 4 '-- add this to go back to previous index
          End If
       End If
       Counter = Counter + 1
    Loop
Next IndexSearch

【讨论】:

  • IndexSearch + 4 是做什么的?
  • 请记住,循环仍会尝试迭代到原始ArrayListTaskDetails.Count - 1,从而导致ArrayListTaskDetails (IndexSearch) 出现下标超出范围错误。 VBScript 在循环期间不会更新为 fromto 值。
  • @AutomatedChaos 已经警告 OP 关于 infinity ;) 并试图让他了解代码发生了什么。所以OP可以设置属性错误处理,验证..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-04
  • 1970-01-01
  • 2020-09-09
  • 2019-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多