旋转列表(T)

时间:2018-06-13 08:19:24

标签: vb.net list linq rotation

问题是如何使用 LINQ 最终 Lambda 呈现 DispList RotateList 函数的良好工作代码。提前谢谢

Class CalcProc
    Property Year As Integer
    Property Type As String
    Property Count As Integer
    Property Total As Integer
    Property Proc As Decimal
End Class
Sub CreateListOfT()
    Dim List As New List(Of CalcProc)

    List.Add(New CalcProc With {.Year = 2013, .Type = "A", .Count = 12, .Total = 20, .Proc = calcP(.Count, .Total)})
    List.Add(New CalcProc With {.Year = 2013, .Type = "B", .Count = 22, .Total = 30, .Proc = calcP(.Count, .Total)})
    List.Add(New CalcProc With {.Year = 2014, .Type = "C", .Count = 32, .Total = 40, .Proc = calcP(.Count, .Total)})
    List.Add(New CalcProc With {.Year = 2015, .Type = "D", .Count = 42, .Total = 50, .Proc = calcP(.Count, .Total)})
    List.Add(New CalcProc With {.Year = 2016, .Type = "E", .Count = 52, .Total = 60, .Proc = calcP(.Count, .Total)})
    DispListOfT(List)
    RotateListOfT(List)

End Sub
Private Function DispListOfT(Of T)(ByVal dList As IList(Of T))

    If Not dList.Any Then
        MsgBox("NOTHING to display!", vbCritical, MethodBase.GetCurrentMethod.Name())
        End
    End If

    Dim fields() = dList.First.GetType.GetProperties
    Dim ListColumns = (From x In fields Select x.Name).ToList()
    Console.WriteLine(String.Join(",", ListColumns.ToArray))

    Dim sb As New Text.StringBuilder
    For Each item In dList
        sb.Length = 0
        For Each field In fields
            Dim p = item.GetType.GetProperty(field.Name)
            sb.Append(p.GetValue(item, Nothing)) : sb.Append(",")
        Next
        Console.WriteLine(Left(sb.ToString, sb.Length - 1))
    Next

End Function

Public Function RotateListOfT(Of T)(ByVal dList As IList(Of T))

    Dim sa As New Text.StringBuilder
    Dim fields() = dList.First.GetType.GetProperties
    Dim dCount As Integer
    Dim Modulo As Integer = dList.Count \ 4
    For i As Integer = 0 To Modulo - 1
        For Each field In fields
            sa.Append(field.Name)
            sa.Append(vbTab)
            For Each item In dList
                If dCount Mod Modulo = i Then
                    Dim p = item.GetType.GetProperty(field.Name)
                    sa.Append(p.GetValue(item, Nothing))
                    sa.Append(vbTab)
                End If
                dCount += 1
            Next
            Console.WriteLine(sa.ToString)
            sa.Length = 0
        Next
    Next
End Function
Function calcP(a As Integer, b As Integer) As Decimal
    Return Round(a * 100.0 / b, 2)
End Function

List(Of T)

Year, Type, Count, Total, Proc
2013,A,12,20,60
2013,B,22,30,73.33
2014,C,32,40,80
2015,D,42,50,84
2016,E,52,60,86.67

已旋转List(Of T)

Year    2013    2013    2014    2015    2016
Type    A       B       C       D       E
Count   12      22      32      42      52
Total   20      30      40      50      60
Proc    60      73.33   80      84      86.67

1 个答案:

答案 0 :(得分:2)

以下是我对Sub的重写。虽然您可以使用For Each替换剩余的List.ForEach循环,但这样做没有任何优势,我认为它不太清楚。 LINQ非常适合将序列转换为结果,然后将其用于I / O.

由于您知道参数dListIList(Of T),因此您知道T的每个成员都具有相同的属性,因此没有理由检索每个项目的属性。

最后我使用lambda语法作为LINQ,因为它有助于嵌套在其他函数调用中。

Public Sub DispListOfT(Of T)(ByVal dList As IList(Of T))
    If Not dList.Any Then
        'MsgBox("NOTHING to display!", vbCritical, MethodBase.GetCurrentMethod.Name())
        Return
    End If

    Dim props = dList.First.GetType.GetProperties
    Console.WriteLine(String.Join(",", props.Select(Function(p) p.Name)))

    For Each item In dList
        Console.WriteLine(String.Join(",", props.Select(Function(p) p.GetValue(item))))
    Next
End Sub

Public Sub RotateListOfT(Of T)(ByVal dList As IList(Of T))
    For Each prop In dList.First.GetType.GetProperties
        Console.Write(prop.Name)
        Console.Write(vbTab)
        Console.WriteLine(String.Join(vbTab, dList.Select(Function(item) prop.GetValue(item))))
    Next
End Sub

如果我正在编写一个程序来执行此操作,我可能会将List的旋转与输出旋转的List分开。此外,使用Reflection从类型中获取属性名称应该是非常不寻常的,您应该已经知道要处理的类型并将输出方法添加到类的类中,除非您的程序处理大量不同的列表因某种原因而上课。