Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 转置作为IEnumerable的IEnumerable存在的2D数组_.net_Vb.net_Linq - Fatal编程技术网

.net 转置作为IEnumerable的IEnumerable存在的2D数组

.net 转置作为IEnumerable的IEnumerable存在的2D数组,.net,vb.net,linq,.net,Vb.net,Linq,如何在VB.NET中执行此操作?我尝试在IEnumerable上使用LINQZIP方法,但它不适用于2个以上的数组 下面是一个Python示例,说明了我正在尝试做的事情(我得到了p-嵌套IEnumerable-需要q-另一个嵌套IEnumerable): NET版本的Zip不会像Python那样处理任意数量的数组。您需要给Zip打两次电话: Dim first As String() = { "a", "b", "c" } Dim second As Integer() = { 1, 2, 3

如何在VB.NET中执行此操作?我尝试在IEnumerable上使用LINQZIP方法,但它不适用于2个以上的数组

下面是一个Python示例,说明了我正在尝试做的事情(我得到了p-嵌套IEnumerable-需要q-另一个嵌套IEnumerable):


NET版本的Zip不会像Python那样处理任意数量的数组。您需要给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
另一种选择是使用包含索引的重载。这种方法依赖于您正在使用的允许按索引访问的类型。为了提高性能,我不建议用
ElementAt
方法代替索引访问。此外,此方法假定所有集合的长度相同,否则将引发异常。其工作如下:

Dim query2 = first.Select(Function(f, i) New With { .First = f, .Second = second(i), .Third = third(i) })

编辑:一个想法是直接利用Python并从VB.NET调用它。我真的不确定这将如何处理,并将有一个学习曲线来设置这一切。搜索“从c#调用python”或“vb.net”以了解有关该主题的更多信息

挑战在于您无法动态创建匿名类型。我想到的最接近的方法是使用.NET4.0。要在VB.NET中使用C#的
dynamic
关键字,您应该能够在不指定类型的情况下初始化对象,例如
Dim o=5
,因为它实际上是一个
对象。您可能需要将
选项推断设置为打开
选项严格关闭
,以实现这一点

下面的代码需要数组作为输入。不幸的是,在尝试访问
计数时,混合使用动态类型和其他
IEnumerable
变得很困难。Jon Skeet在这里有一篇相关文章:。出于这个原因,我坚持使用数组;可以将其更改为
List
,以使用
Count
属性,但绝对不是不需要大量工作的混合

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#同等品(适用于任何感兴趣的人)

string[]first={“a”、“b”、“c”};
int[]秒={1,2,3};
字符串[]第三个={“x”,“y”,“z”};
bool[]fourth={true,false,true};
var list=新列表{第一、第二、第三、第四};
bool isValidLength=list.All(l=>l.Length==list[0].Length);
如果(isValidLength)
{
var result=新列表();
对于(int i=0;i
如果要支持特定数量的IEnumerable,可以返回某种元组或类似结构(如)。对于一般情况,您必须进行某种缓存,最终在所有可枚举项中只有一种类型的项。大概是这样的:

Public Function Transpose(Of T)(ByVal source As IEnumerable(Of IEnumerable(Of T))) As IEnumerable(Of IEnumerable(Of T))
    If source is Nothing then Throw New ArgumentNullException("source")
    Return New TransposeEnumerable(Of T)(source)
End Function

Friend NotInheritable Class TransposeEnumerable(Of T)
    Implements IEnumerable(Of IEnumerable(Of T))

    Public Sub New(ByVal base As IEnumerable(Of IEnumerable(Of T)))
        _base = base
    End Sub

    Private ReadOnly _base As IEnumerable(Of IEnumerable(Of T))

    Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of IEnumerable(Of T)) Implements System.Collections.Generic.IEnumerable(Of IEnumerable(Of T)).GetEnumerator
        Return New TransposeEnumerator(Me)
    End Function

    Private Function GetObjectEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
        Return Me.GetEnumerator()
    End Function

    Private NotInheritable Class TransposeEnumerator
        Implements IEnumerator(Of IEnumerable(Of T))

        Public Sub New(ByVal owner As TransposeEnumerable(Of T))
            _owner = owner
            _sources = owner.Select(Function(e) e.GetEnumerator()).ToList()
        End Sub

        Private disposedValue As Boolean
        Public Sub Dispose() Implements IDisposable.Dispose
            If Not Me.disposedValue Then
                If _sources IsNot Nothing Then
                    For Each e In _sources
                        If e IsNot Nothing Then e.Dispose()
                    Next
                End If
            End If
            Me.disposedValue = True
        End Sub

        Private ReadOnly _owner As TransposeEnumerable(Of T)
        Private _sources As New List(Of IEnumerator(Of T))
        Private _current As IEnumerable(Of T)

        Public ReadOnly Property Current() As IEnumerable(Of T) Implements System.Collections.Generic.IEnumerator(Of IEnumerable(Of T)).Current
            Get
                Return _current
            End Get
        End Property

        Private ReadOnly Property CurrentObject() As Object Implements System.Collections.IEnumerator.Current
            Get
                Return Me.Current
            End Get
        End Property

        Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
            Dim success As Boolean = _sources.All(Function(s) s.MoveNext())
            If success Then
                _current = _sources.Select(Function(s) s.Current).ToList().AsEnumerable()
            End If
            Return success
        End Function

        Public Sub Reset() Implements System.Collections.IEnumerator.Reset
            Throw New InvalidOperationException("This enumerator does not support resetting.")
        End Sub

    End Class
End Class

嵌套式拉链也是我尝试过的。但我的原始收藏是开放式的,可以有3个以上的IEnumerable。我试图将这个Zip放在一个循环中:first.Zip(第二,函数(f,s){f,s})。问题是返回的f是IEnumerable,而s是IEnumerable的内容。然后我尝试用SelectMany展平f,结果被卡住了。。。您通过使用.First和.Second解决了这个问题,但如果我想运行开放式循环,就不能这样做。有什么想法吗?这比我目前能想到的任何东西都好,它解决了我眼前的问题,同时教了我一些新的技巧-非常感谢!但愿我有更多的代表投票给你…呸!这比我一次能消化的还要多。当然这里有一些很酷的概念。我得花点时间在这上面。。。谢谢当前在循环中使用yield创建新的IEnumerable。我仍然想看看是否可以使用嵌套的Zip。。。
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();
    }
}
Public Function Transpose(Of T)(ByVal source As IEnumerable(Of IEnumerable(Of T))) As IEnumerable(Of IEnumerable(Of T))
    If source is Nothing then Throw New ArgumentNullException("source")
    Return New TransposeEnumerable(Of T)(source)
End Function

Friend NotInheritable Class TransposeEnumerable(Of T)
    Implements IEnumerable(Of IEnumerable(Of T))

    Public Sub New(ByVal base As IEnumerable(Of IEnumerable(Of T)))
        _base = base
    End Sub

    Private ReadOnly _base As IEnumerable(Of IEnumerable(Of T))

    Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of IEnumerable(Of T)) Implements System.Collections.Generic.IEnumerable(Of IEnumerable(Of T)).GetEnumerator
        Return New TransposeEnumerator(Me)
    End Function

    Private Function GetObjectEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
        Return Me.GetEnumerator()
    End Function

    Private NotInheritable Class TransposeEnumerator
        Implements IEnumerator(Of IEnumerable(Of T))

        Public Sub New(ByVal owner As TransposeEnumerable(Of T))
            _owner = owner
            _sources = owner.Select(Function(e) e.GetEnumerator()).ToList()
        End Sub

        Private disposedValue As Boolean
        Public Sub Dispose() Implements IDisposable.Dispose
            If Not Me.disposedValue Then
                If _sources IsNot Nothing Then
                    For Each e In _sources
                        If e IsNot Nothing Then e.Dispose()
                    Next
                End If
            End If
            Me.disposedValue = True
        End Sub

        Private ReadOnly _owner As TransposeEnumerable(Of T)
        Private _sources As New List(Of IEnumerator(Of T))
        Private _current As IEnumerable(Of T)

        Public ReadOnly Property Current() As IEnumerable(Of T) Implements System.Collections.Generic.IEnumerator(Of IEnumerable(Of T)).Current
            Get
                Return _current
            End Get
        End Property

        Private ReadOnly Property CurrentObject() As Object Implements System.Collections.IEnumerator.Current
            Get
                Return Me.Current
            End Get
        End Property

        Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
            Dim success As Boolean = _sources.All(Function(s) s.MoveNext())
            If success Then
                _current = _sources.Select(Function(s) s.Current).ToList().AsEnumerable()
            End If
            Return success
        End Function

        Public Sub Reset() Implements System.Collections.IEnumerator.Reset
            Throw New InvalidOperationException("This enumerator does not support resetting.")
        End Sub

    End Class
End Class