如果我有一个List(Of x)和一个List(Of y),是否可以同时迭代这两个?
像
这样的东西for each _x as X, _y as Y in List(of x), List(of y)
if _x.item = _y.item then
'do something
end if
next
这些列表可能有不同的大小。
我正在使用.Net2.0,我怀疑这是我的垮台,因为我有一种感觉LINQ可以通过加入常见id上的列表轻松解决问题。
答案 0 :(得分:5)
你可以使用老式的for循环。像
这样的东西For ii As Integer = 0 To Math.Min(list1.Count, list2.Count)
If list1(ii) = list2(ii) Then
End If
Next
答案 1 :(得分:4)
IIRC,.Net 4.0将为IEnumerable提供.Zip()
扩展方法,已经这样做了。
与此同时,建立自己的并不难。令人惊讶的是,虽然其他几个答案非常接近,但他们都至少有一个问题。希望他们会得到纠正。在此期间,这应该在VB.Net中使用强类型枚举器,使用未知类型的正确比较,并正确处理枚举器,来执行您想要的操作:
Using xe As IEnumerator(Of X) = List1.GetEnumerator(), _
ye As IEnumerator(Of Y) = List2.GetEnumerator()
While xe.MoveNext() AndAlso ye.MoveNext()
If xe.Current.Equals(ye.Current) Then
''// do something
End If
End While
End Using
现在让我们把它放到一个函数中,你可以将自己的代理传递给:
Public Shared Sub ZipAction(Of X, Y)(ByVal source1 As IEnumerable(Of X), ByVal source2 As IEnumerable(Of Y), _
ByVal compare As Func(Of X, Y, Boolean), Byval OnEquals As Action(Of X, Y))
Using xe As IEnumerator(Of X) = source1.GetEnumerator(), _
ye As IEnumerator(Of Y) = source2.GetEnumerator()
While xe.MoveNext() AndAlso ye.MoveNext()
If compare(xe.Current, ye.Current) Then
OnEquals(xe.Current, ye.Current)
End If
End While
End Using
End Sub
最后,由于这些委托类型在.Net 3.5之前不可用,您可以像这样在.Net 2.0中轻松声明它们:
Public Delegate Sub Action(Of T1, T2) ( _
arg1 As T1, _
arg2 As T2 _
)
Public Delegate Function Func(Of T1, T2, TResult) ( _
arg1 As T1, _
arg2 As T2, _
) As TResult
要使用此代码,您可以执行以下操作:
Public Class X
Public Item As String
''//...
End Class
Public Class Y
Public Item As String
''//...
End Class
Public Class Test
Private Function CompareXtoY(ByVal arg1 As X, ByVal arg2 As Y) As Boolean
Return arg1.Item = arg2.Item
End Function
Private Sub OnList1ItemMatchesList2Item(ByVal arg1 As X, ByVal arg2 As Y)
''// Do something...
End Sub
Private list1 As List(Of X) = GetXList()
Private list2 As List(Of Y) = GetYList()
Public Sub TestZip()
ZipAction(list1, list2, AddressOf CompareXtoY, AddressOf OnList1ItemMatchesList2Item)
End Sub
End Class
如果这是C#,我会让函数成为迭代器块,并且每个匹配对都“返回”,而不是要求你传递一个Action委托。
答案 2 :(得分:2)
不,不是在vb.net中使用vb循环结构。
然而,您可以使用枚举器自行完成:
Sub MyOwnIENumeration()
Dim a As List(Of String), b As List(Of String)
Dim EnmA As System.Collections.Generic.IEnumerator(Of String) = a.GetEnumerator
Dim EnmB As System.Collections.Generic.IEnumerator(Of String) = b.GetEnumerator
If EnmA.MoveNext() And EnmB.MoveNext() Then
Do
If EnmA.Current = EnmB.Current Then
Debug.Print("list matched on " & EnmA.Current)
If Not EnmA.MoveNext() Then Exit Do
If Not EnmB.MoveNext() Then Exit Do
ElseIf EnmA.Current < EnmB.Current Then
If Not EnmA.MoveNext() Then Exit Do
Else
If Not EnmB.MoveNext() Then Exit Do
End If
Loop
End If
EnmA.Dispose() : EnmB.Dispose()
End Sub
答案 3 :(得分:2)
您必须手动访问枚举器。在C#中:
using (IEnumerator<X> xe = List1.GetEnumerator())
using (IEnumerator<Y> ye = List2.GetEnumerator()) {
while (xe.MoveNext() && ye.MoveNext()) {
if (xe.Current == ye.Current) {
// do something
}
}
}
答案 4 :(得分:0)
你的意思是没有做一个嵌套循环?
foreach _x as X in List(of x)
foreach _y as Y in List(of y)
if _x.item = _y.item then
'do something
end if
next
不是VB程序员,所以我的语法可能不对,但你明白了。
答案 5 :(得分:0)
我对VB.NET不是很精通,但是这是C#中的一个扩展方法,你可以创建它来做到这一点。我希望你能移植它!
public static class IEnumExtensions
{
public static IEnumerable<KeyValuePair<T, U>> EnumTwoCollections<T, U>(this IEnumerable<T> list1, IEnumerable<U> list2)
{
var enumerator1 = list1.GetEnumerator();
var enumerator2 = list2.GetEnumerator();
bool moveNext1 = enumerator1.MoveNext();
bool moveNext2 = enumerator2.MoveNext();
while (moveNext1 || moveNext2)
{
T tItem = moveNext1 ? enumerator1.Current : default(T);
U uItem = moveNext2 ? enumerator2.Current : default(U);
yield return new KeyValuePair<T, U>(tItem, uItem);
moveNext1 = enumerator1.MoveNext();
moveNext2 = enumerator2.MoveNext();
}
}
}
用法:
List<int> intList = new List<int>();
List<string> stringList = new List<string>();
for (int i = 1; i <= 10; i++)
{
intList.Add(i);
stringList.Add((i * i).ToString());
}
foreach (var items in intList.EnumTwoCollections(stringList))
{
Console.WriteLine(items.Key + " , " + items.Value);
}
现在注意到您没有使用.NET 3.5,因此您可能也无法使用扩展方法。把它放在一个帮助类中你就可以这样调用它:
foreach(KeyValuePair<int,string> kvp in Helper.EnumTwoCollections(intList,stringList))
{
...
}
答案 6 :(得分:0)
您可以使用每个IEnumerable的GetEnumerator()函数来完成它。
您可以执行以下操作:
// Assume List1 and List2 are IEnumerable variables
Dim list1 As IEnumerator = List1.GetEnumerator()
Dim list2 As IEnumerator = List2.GetEnumerator();
While list1.MoveNext() And list2.MoveNext()
If list1.Current = list2.Current Then
// Do Something
End If
End While
以下是来自MSDN
的更多信息