.NET中如何对List中的数据进行部分转置?
.NET(VB.NET)实现VoltageList转置的可行方案
以下是针对你的场景(从时序数据库获取的VoltageList(继承自List(Of Voltage))转置需求)的几种.NET技术实现方案,均适配VB.NET环境:
1. LINQ 查询(最常用、代码简洁)
利用LINQ的投影与集合转换能力,适合通道数量固定的结构化场景。假设你的Voltage类及目标转置类定义如下:
Public Class Voltage Public Property Timestamp As DateTime Public Property Channel1 As Double? Public Property Channel2 As Double? ' 扩展其他电压通道属性... End Class Public Class VoltageList Inherits List(Of Voltage) Public Function Transpose() As List(Of ChannelVoltage) ' 实现逻辑见下方 End Function End Class ' 转置后的目标数据结构示例 Public Class ChannelVoltage Public Property ChannelName As String Public Property Values As List(Of (Timestamp As DateTime, Value As Double?)) End Class
Transpose方法的LINQ实现:
Public Function Transpose() As List(Of ChannelVoltage) ' 定义通道映射:通道名称 → 取值逻辑 Dim channelMappings = { ("Channel1", Function(v As Voltage) v.Channel1), ("Channel2", Function(v As Voltage) v.Channel2) ' 按需添加更多通道 } Return channelMappings.Select(Function(map) New ChannelVoltage With { .ChannelName = map.Item1, .Values = Me.Select(Function(v) (v.Timestamp, map.Item2(v))).ToList() }).ToList() End Function
2. 反射(处理动态通道场景)
如果Voltage类的电压通道属性数量不固定(动态增减),可通过反射自动遍历属性实现转置,无需硬编码通道名称:
Imports System.Reflection Public Function Transpose() As List(Of ChannelVoltage) Dim result As New List(Of ChannelVoltage)() ' 获取Voltage类中除Timestamp外的所有数值型属性(即电压通道) Dim channelProperties = GetType(Voltage).GetProperties() _ .Where(Function(p) p.Name <> NameOf(Voltage.Timestamp) AndAlso (p.PropertyType Is GetType(Double) OrElse p.PropertyType Is GetType(Double?)) ).ToList() For Each prop In channelProperties result.Add(New ChannelVoltage With { .ChannelName = prop.Name, .Values = Me.Select(Function(v) (v.Timestamp, CType(prop.GetValue(v), Double?))).ToList() }) Next Return result End Function
优化提示:可缓存
channelProperties集合避免重复反射,提升性能。
3. DataTable 转置(兼容传统数据交互)
若需转置后的数据与WinForms/WPF数据控件(如DataGridView)直接交互,可先将VoltageList转换为DataTable,再完成行列转置:
Imports System.Data Public Function Transpose() As DataTable ' 1. 填充原始数据到DataTable Dim sourceTable As New DataTable() sourceTable.Columns.Add(NameOf(Voltage.Timestamp), GetType(DateTime)) sourceTable.Columns.Add("Channel1", GetType(Double?)) sourceTable.Columns.Add("Channel2", GetType(Double?)) ' 添加其他通道列... For Each v In Me sourceTable.Rows.Add(v.Timestamp, v.Channel1, v.Channel2) Next ' 2. 创建转置后的DataTable结构 Dim transposedTable As New DataTable() transposedTable.Columns.Add("ChannelName") ' 将所有时间戳作为转置后的列 For Each row In sourceTable.Rows transposedTable.Columns.Add(row(NameOf(Voltage.Timestamp)).ToString(), GetType(Double?)) Next ' 3. 填充转置数据 For Each col In sourceTable.Columns.Cast(Of DataColumn)().Where(Function(c) c.ColumnName <> NameOf(Voltage.Timestamp)) Dim newRow = transposedTable.NewRow() newRow("ChannelName") = col.ColumnName For i = 0 To sourceTable.Rows.Count - 1 newRow(i + 1) = sourceTable.Rows(i)(col) Next transposedTable.Rows.Add(newRow) Next Return transposedTable End Function
4. 手动循环遍历(最高性能)
若数据量极大且对性能要求苛刻,直接手动循环遍历集合,避免LINQ/反射的额外开销:
Public Function Transpose() As List(Of ChannelVoltage) ' 初始化各通道的数值列表 Dim channel1Vals As New List(Of (DateTime, Double?))() Dim channel2Vals As New List(Of (DateTime, Double?))() ' 初始化其他通道列表... ' 遍历原始数据填充各通道 For Each v In Me channel1Vals.Add((v.Timestamp, v.Channel1)) channel2Vals.Add((v.Timestamp, v.Channel2)) ' 填充其他通道 Next ' 组装转置结果 Return New List(Of ChannelVoltage) From { New ChannelVoltage With {.ChannelName = "Channel1", .Values = channel1Vals}, New ChannelVoltage With {.ChannelName = "Channel2", .Values = channel2Vals} ' 添加其他通道 } End Function
内容的提问来源于stack exchange,提问作者Paul Johnson
相关产品推荐
相关产品推荐

