【问题标题】:Vb.Net LINQ query nested listVb.Net LINQ 查询嵌套列表
【发布时间】:2014-05-24 15:43:02
【问题描述】:

我有 cPoint 对象的列表。每个 cPoint 都有 cPosition 对象的列表。我必须进行查询,只返回其 cPositions 满足条件的 cPoints,并且每个 cPoint 必须只包含那些满足条件的 cPositions。 LINQ可以吗?

'classes
Public Class cPoint
    Private _PointName As String
    Public Positions As colPositions
    '...
End Class

Public Class cPosition
    Private _X As Double
    Private _Y As Double
    Private _Z As Double
    Private _IntervalStart As Long
    '...
End Class

Public Class cPoints
    Inherits System.ComponentModel.BindingList(Of cPoint)
End Class

Public Class cPositions
    Inherits System.ComponentModel.BindingList(Of cPosition)
End Class

我做的最接近的事情是这个查询,但它不返回过滤的 cPoints。查询中的每个项目都有两个对象:1. 过滤的点(带有未过滤的子位置)和 2. 属于该点的过滤位置。

Dim PtList As cPoints
'...
'my query 
Dim query = (From pt In PtList
             From pos In pt.Positions
             Where (pos.IntervalStart < 222)
             Select New With {Key .PT = pt,
             Key .PTPOS = (From position In pt.Positions Where (position.IntervalStart < 222)).ToList}).Distinct

【问题讨论】:

  • 这在Linq中很简单,看我的回答。
  • 查看我的更新。建议:C# 还不错:)

标签: vb.net linq


【解决方案1】:

所以你想要位置 ALL 间隔大于 222 的点?只需使用 All Linq 方法,如下例:

Module Module1
'classes
Public Class cPoint
    Private _PointName As String
    Public Positions As cPositions

    ''' <summary>
    ''' Needed because we want to construct cPoints object using cPosition list within Linq
    ''' </summary>
    ''' <param name="posList"></param>
    ''' <remarks></remarks>
    Public Sub New(posList As IEnumerable(Of cPosition))
        Positions = New cPositions
        For Each cp As cPosition In posList
            Me.Positions.Add(cp)
        Next
    End Sub

    'default
    Public Sub New()

    End Sub
End Class

Public Class cPosition
    Private _X As Double
    Private _Y As Double
    Private _Z As Double
    Private _IntervalStart As Long

    Public Sub New(x As Double, y As Double, z As Double, iss As long)
        _X = x
        _Y = y
        _Z = z
        _IntervalStart = iss
    End Sub


    ''' <summary>
    ''' Added a property to access from outside class
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property IntervalStart As Long
        Get
            Return _IntervalStart
        End Get
        Set(value As Long)
            _IntervalStart = value
        End Set
    End Property
End Class

Public Class cPoints
    Inherits System.ComponentModel.BindingList(Of cPoint)
End Class

Public Class cPositions
    Inherits System.ComponentModel.BindingList(Of cPosition)
End Class

Sub Main()

    Dim ptlist As cPoints = New cPoints
    Dim point1 = New cPoint
    point1.Positions = New cPositions
    point1.Positions.Add(New cPosition(1, 2, 3, 4))
    point1.Positions.Add(New cPosition(1, 2, 3, 1000))
    point1.Positions.Add(New cPosition(1, 2, 3, 2000))
    point1.Positions.Add(New cPosition(1, 2, 3, 1))

    Dim point2 = New cPoint
    point2.Positions = New cPositions
    point2.Positions.Add(New cPosition(1, 2, 3, 1))
    point2.Positions.Add(New cPosition(1, 2, 3, 2))
    point2.Positions.Add(New cPosition(1, 2, 3, 444))
    point2.Positions.Add(New cPosition(1, 2, 3, 555))

    ptlist.Add(point1)
    ptlist.Add(point2)

    'selects all the points in ptlist that have all their positions with interval start more than 222.
    Dim result = From pt In ptlist
                 Where pt.Positions.All(Function(l As cPosition)
                                            'put whatever condition here.
                                            Return l.IntervalStart > 222
                                        End Function)
                Select pt

    'select all the points. each point, will have all the positions that are less than 222.
    Dim result2 = From pt In ptlist
                  Select New cPoint(pt.Positions.Where(Function(l As cPosition)
                                                           Return l.IntervalStart < 222
                                                       End Function))

    For Each a In result2
        Console.WriteLine(a.Positions.Count)
    Next


End Sub

End Module

【讨论】:

  • 不,我好像还不够清楚。 (其中 pt.Positions.Any)将返回我想要的所有点。问题是我希望那些返回的点只有符合条件的 cPositions 列表的一部分。例如,我有点列表: Point1, Name=1(Position1 x=0,y=0,z=0,IntervalStart=15) (Position2 x=100,y=200,z=15,IntervalStart=250) Point2 Name=2(Position1 x=0,y=0,z=0,IntervalStart=352) (Position2 x=100,y=200,z=15,IntervalStart=20) 最终结果应该是:Point1, Name=1 (Position1 x=0,y=0,z=0,IntervalStart=15) Point2 Name=2 (Position2 x=100,y=200,z=15,IntervalStart=20)
  • 这对 Linq 来说仍然很简单,但是您需要创建新的 Point 对象:我创建了构造函数来帮助解决这个问题。查看我的更新答案
  • 谢谢,但是创建新点是个问题,因为我想保留对原始点的引用。过滤点/位置的每一个变化都应该反映原始点,反之亦然。
  • 您的问题是使用 Linq。我回答了。如果您想要复杂的对象来维护列表中的数据和其他列表中的视图,只需创建两个 List 属性 {get;set;} 你需要帮助吗?请接受我的回答并针对您需要的其他问题提出另一个问题。
  • 感谢您的回答。我知道如何以不同的方式解决问题,我只是在徘徊是否可以使用 LINQ。我的错误是我在第一个问题中没有足够清楚地解释我想要什么。再次感谢!
猜你喜欢
  • 2021-06-12
  • 2017-11-29
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多