经过两年的C#,我的VB.NET有点生疏了。我有两个列表。我们称它们为originalList和targetList。这是我的C#代码:
for(int i = 0; i<originalList.Count; i++)
{
bool isMatch = false;
foreach (string t in targetList)
{
if(String.Compare(originalList[i], t, true) == 0)
{
isMatch = true;
break;
}
}
if(isMatch)
{
originalList.RemoveAt(i);
i--;
}
}
我的VB.NET代码就是这样:
Dim i as Integer
For i = 0 To originalList.Count - 1
Dim isMatch as boolean = false
For Each t As String In targetList
If String.compare(originalList(i), t, true) = 0 Then
isMatch = true
Exit For
End If
Next
If isMatch Then
originalList.RemoveAt(i)
i -= 1
End If
Next
但是我的VB.NET代码出现了索引超出范围的错误。我在哪里弄错了?
答案 0 :(得分:21)
考虑到这一点 - 这是一种更优雅的方式来实现您正在尝试执行的操作 - 即从目标列表中显示的原始列表中删除项目。请考虑以下列表:
Dim OriginalList As New List(Of String)(New String() {"a", "b", "c", "d"})
Dim TargetList As New List(Of String)(New String() {"a", "b", "c"})
以下是我如何删除目标中出现的原始内容...
OriginalList.RemoveAll(Function(OriginalItem) TargetList.Contains(OriginalItem))
将在C#中编写:
OriginalList.RemoveAll(OriginalItem => TargetList.Contains(OriginalItem));
用于完成任务的代码越少,编码错误的可能性就越小。
侧注: 这与测试子集的算法非常相似。如果你想知道集合A是否是B的一个子集,那么你可以迭代B从A中删除任何相应的项目。一旦你完成了对B的迭代,如果A中还有任何项目,那么它就不是B的子集。如果没有剩下的项目,则它是B的子集。
答案 1 :(得分:14)
问题是如何评估结束条件。在C#中,每次循环时,都会检查originalList.Count
。在VB.NET版本中,循环的结束步骤在进入循环时计算一次。
来自MSDN:迭代次数。 Visual Basic仅在循环开始之前评估迭代值start,end和step一次。如果语句块更改结束或步骤,则这些更改不会影响循环的迭代。
也就是说,所采用的方法并不高效,因为它可能是使用数组支持的列表,这将涉及大量数据移动。如果元素与目标列表不匹配(如果它们不执行任何操作),则简单地将元素复制到新列表可能会更快,然后在完成后设置originalList = newList。
答案 2 :(得分:7)
Dim i as integer = 0
Dim t as String
For I = originalList.Count to 1 Step -1
for each t in targetList
if String.compare(originalList(i), t, true) = 0 then
originalList.RemoveAt(I)
exit for
end if
next t
Next I
For ....步骤-1是您可能不熟悉的部分,因为它是VB.NET的基本遗产的一部分。
当遍历集合以通过数字索引移除项目时,您希望从最后开始并继续前进。这将删除计数和要删除的项目的任何问题。
如果C#示例看起来像这样
,它会更清晰for(int i = originalList.Count; i<0; i--)
{
foreach (string t in targetList)
{
if(String.Compare(originalList[i], t, true) == 0)
{
originalList.RemoveAt(i);
break;
}
}
}
答案 3 :(得分:2)
我会把它变成一个while循环来使条件更清晰:
dim i as integer = 0
While i < originalList.Count
dim isMatch as boolean = false
for each t as string in targetList
if String.compare(originalList(i), t, true) = 0 then
isMatch = true
Exit for
end if
next
if isMatch then
originalList.RemoveAt(i)
else
i += 1
end if
next
答案 4 :(得分:0)
如果您要从枚举内联中删除项目,请务必向后迭代。
答案 5 :(得分:0)
使用:
Dim i as Integer
For i = 0 To originalList.Count - 1
Dim isMatch as boolean = false
For Each t as string In targetList
If String.compare(originalList(i), t, true) = 0 Then
isMatch = true
Exit For
End If
Next
If isMatch Then
originalList.RemoveAt(i)
i -= 1
End If
Next
最多需要originalList.Count
而不是originalList.Count-1
。
答案 6 :(得分:-1)
在我看来,这是一个问题,如何索引你的字符串,而不是你的for循环。使用调试器逐行执行,您将发现问题。我不想让你省力,因为它将来会帮助你。 :)
答案 7 :(得分:-1)
如果我正确地跟踪你的循环,并且原始列表中的第一项是匹配的,那么你将从索引0处的原始列表中删除该字符串,然后将其减少为-1,这不是当你去检查下一个项目时,有效的索引值。
在我看来,您需要检查您的索引计数,如果您低于0,请将其重置为0,以便能够再次从头开始。