La version .NET de Zip ne sera pas gérer un nombre arbitraire de tableaux comme le ferait Python. Vous aurez besoin d'appeler deux fois Zip:
Dim first As String() = { "a", "b", "c" }
Dim second As Integer() = { 1, 2, 3 }
Dim third As String() = { "x", "y", "z" }
Dim query = first.Zip(second, Function(f, s) New With { .First = f, .Second = s }) _
.Zip(third, Function(o, t) New With { o.First, o.Second, .Third = t })
For Each item in query
Console.WriteLine("{0}, {1}, {2}", item.First, item.Second, item.Third)
Next
Une autre option serait d'utiliser le Enumerable.Select
method surchargé qui inclut l'indice. Cette approche repose sur les types avec lesquels vous travaillez permettant l'accès par index. Je ne recommanderais pas de substituer l'accès à l'index par la méthode ElementAt
à des fins de performances. En outre, cette approche suppose que toutes les collections ont la même longueur, sinon elle lèvera une exception. Il fonctionne comme suit:
Dim query2 = first.Select(Function(f, i) New With { .First = f, .Second = second(i), .Third = third(i) })
EDIT: Une pensée est de tirer parti de Python directement et appeler à partir VB.NET. Je ne suis pas vraiment sûr de la façon dont cela sera traité, et il y aura une courbe d'apprentissage pour tout mettre en place. Recherchez "appel python de C#" ou de "vb.net" pour plus d'informations sur ce sujet.
Le défi est que vous ne pouvez pas créer dynamiquement un type anonyme. L'approche la plus proche que je suis venu avec est d'utiliser 0. NET 4.0 ExpandoObject
. Pour utiliser le mot-clé dynamic
de C# dans VB.NET, vous devriez être en mesure d'initialiser un objet sans spécifier le type, tel que Dim o = 5
car c'est vraiment un object
en dessous. Vous devrez probablement définir Option Infer On
et Option Strict Off
pour y parvenir.
Le code suivant attend des tableaux en entrée. Malheureusement, le mélange de types dynamiques et d'autres IEnumerable<T>
devient difficile lorsque vous tentez d'accéder au Count
. Jon Skeet a un article pertinent à ce sujet ici: Gotchas in dynamic typing. Pour cette raison, je suis resté avec des tableaux; il peut être changé en List<T>
pour utiliser la propriété Count
, mais certainement pas un mélange sans beaucoup de travail.
VB.NET
Dim first As String() = { "a", "b", "c" }
Dim second As Integer() = { 1, 2, 3 }
Dim third As String() = { "x", "y", "z" }
Dim fourth As Boolean() = { true, false, true }
Dim list As New List(Of Object) From { first, second, third, fourth }
' ensure the arrays all have the same length '
Dim isValidLength = list.All(Function(c) c.Length = list(0).Length)
If isValidLength
Dim result As New List(Of ExpandoObject)()
For i As Integer = 0 To list(i).Length - 1
Dim temp As New ExpandoObject()
For j As Integer = 0 To list.Count - 1
CType(temp, IDictionary(Of string, Object)).Add("Property" + j.ToString(), list(j)(i))
Next
result.Add(temp)
Next
' loop over as IDictionary '
For Each o As ExpandoObject In result
For Each p in CType(o, IDictionary(Of string, Object))
Console.WriteLine("{0} : {1}", p.Key, p.Value)
Next
Console.WriteLine()
Next
' or access via property '
For Each o As Object In result
Console.WriteLine(o.Property0)
Console.WriteLine(o.Property1)
Console.WriteLine(o.Property2)
Console.WriteLine(o.Property3)
Console.WriteLine()
Next
End If
C# équivalent (pour toute personne intéressée)
string[] first = { "a", "b", "c" };
int[] second = { 1, 2, 3 };
string[] third = { "x", "y", "z" };
bool[] fourth = { true, false, true };
var list = new List<dynamic> { first, second, third, fourth };
bool isValidLength = list.All(l => l.Length == list[0].Length);
if (isValidLength)
{
var result = new List<ExpandoObject>();
for (int i = 0; i < list[i].Length; i++)
{
dynamic temp = new ExpandoObject();
for (int j = 0; j < list.Count; j++)
{
((IDictionary<string, object>)temp).Add("Property" + j, list[j][i]);
}
result.Add(temp);
}
// loop over as IDictionary
foreach (ExpandoObject o in result)
{
foreach (var p in (IDictionary<string, object>)o)
Console.WriteLine("{0} : {1}", p.Key, p.Value);
Console.WriteLine();
}
// or access property via dynamic
foreach (dynamic o in result)
{
Console.WriteLine(o.Property0);
Console.WriteLine(o.Property1);
Console.WriteLine(o.Property2);
Console.WriteLine(o.Property3);
Console.WriteLine();
}
}
actuellement en utilisant le rendement dans une boucle pour créer de nouveaux IEnumerable. J'aimerai quand même voir s'il est possible de faire avec Zip imbriqué ... – user544111