从列表中递归地删除子父关系
Remove child parent relationship recursively from a list
我有一个包含数据行对象的列表,这些对象具有两个属性,一个 Id 和一个 prentId。一个例子是这样的:
id ParentId
130 -1
131 130
132 131
133 131
134 132
135 131
136 132
137 136
138 136
139 136
143 136
如果从层次结构的角度来看列表,它将如下所示:
130
131
132
134
136
137
138
139
143
133
135
我想做的是创建一个算法,删除父元素与特定 ID 匹配的所有元素和子元素。
例如,如果选择的 ID 为 132,则应删除 ID 为 132、134、136、137、138、139、143 的元素。
到目前为止我尝试的是这样的
Private Function RemoveRecursive(ByRef values As List(Of DataRow), value As String) As List(Of DataRow)
For index As Integer = values.Count - 1 To 0 Step -1
If Not IsDBNull(values(index)("parent")) AndAlso values(index)("parent") = value Then
values.RemoveAt(index)
Return RemoveRecursive(values, value)
value = values(index)("id")
End If
Next
Return values
End Function
根据提供的数据,我假设 133 和 135 也想删除,因为它们是 children 的 131?
实现您想要的目标的一种方法可能是;
- 创建 'tagged' 个条目的空列表
- 遍历列表,如果 ParentID == 131 或 ParentID 在标记条目列表中,则将此节点添加到标记条目
- 从您的原始数据集中删除所有标记的 objects
我试图解决你的问题 (c#):
private static void RemoveRecursive(List<DataRow> values, string valueToRemove) {
DataRow itemToRemove = values.Find(dr => (string)dr["id"] == valueToRemove);
values.Remove(itemToRemove);
IEnumerable<string> children = values.Where(dr => (string)dr["ParentId"] == valueToRemove).Select(dr => (string)dr["id"]);
foreach (string child in children)
RemoveRecursive(values, child);
}
您可以通过以下方式调用此方法:
RemoveRecursive(values, "131");
您还可以添加一些空检查。
离你不远了。您错过了两件事:
- 如果当前行
id
等于搜索值,而不仅仅是 parent
。
- 您在对
RemoveRecursive
的内部调用之后设置重估,因此它使用与初始值相同的值,即它每次只会检查 132
。
1 号只需要扩展您的 if
语句。对于数字 2,我只是将当前 id 值存储在一个新变量中,然后再删除该行并将其传递给递归调用:
Private Function RemoveRecursive(ByRef values As List(Of DataRow), value As String) As List(Of DataRow)
For index As Integer = values.Count - 1 To 0 Step -1
If Not IsDBNull(values(index)("parent")) AndAlso (values(index)("parent") = value OrElse values(index)("id") = value) Then
Dim newValue as integer = values(index)("id").ToString()
values.RemoveAt(index)
RemoveRecursive(values, newValue)
End If
Next
Return values
End Function
parent / child 的一般示例可能会有所帮助。这是乐观的,因为没有错误检查。请注意,Add 和 Remove 方法都被重载了。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim root As New PC(1)
root.AddChild(1, 10)
root.AddChild(1, 11)
root.AddChild(1, 12)
root.AddChild(11, 110)
root.AddChild(11, 111)
root.AddChild(110, 1100)
root.AddChild(110, 1101)
root.AddChild(1100, 11000)
root.AddChild(1100, 11001)
root.AddChild(1101, 11010)
root.RemoveChild(1100)
End Sub
Class PC 'parent child
Dim myID As Integer
Dim parentPC As PC = Nothing
Dim children As New List(Of PC)
Public Sub New(ID As Integer)
Me.myID = ID
End Sub
Public Function AddChild(parent As Integer, child As Integer) As PC
Dim rv As PC
rv = Me.AddChild(Me, parent, child)
Return rv
End Function
Private Function AddChild(aPC As PC, parent As Integer, child As Integer) As PC
Dim rv As PC
Dim addPC As PC
If aPC.myID = parent Then
addPC = New PC(child)
addPC.children = New List(Of PC)
addPC.parentPC = aPC
aPC.children.Add(addPC)
Return addPC
Else
For Each chld As PC In aPC.children
rv = chld.AddChild(chld, parent, child)
If rv IsNot Nothing Then
Exit For
End If
Next
End If
Return rv
End Function
Public Function RemoveChild(child As Integer) As Boolean
Dim rv As Boolean = False
rv = Me.RemoveChild(child, Me)
Return rv
End Function
Private Function RemoveChild(child As Integer, aPC As PC) As Boolean
Dim rv As Boolean = False
If aPC.myID = child Then
For x As Integer = aPC.children.Count - 1 To 0 Step -1
Dim chld As PC = aPC.children(x)
Me.RemoveChild(chld.myID, chld)
Next
aPC.parentPC.children.Remove(aPC)
aPC.children = Nothing
aPC = Nothing
rv = True
Else
For Each chld As PC In aPC.children
rv = Me.RemoveChild(child, chld)
If rv Then
Exit For
End If
Next
End If
Return rv
End Function
End Class
我有一个包含数据行对象的列表,这些对象具有两个属性,一个 Id 和一个 prentId。一个例子是这样的:
id ParentId
130 -1
131 130
132 131
133 131
134 132
135 131
136 132
137 136
138 136
139 136
143 136
如果从层次结构的角度来看列表,它将如下所示:
130
131
132
134
136
137
138
139
143
133
135
我想做的是创建一个算法,删除父元素与特定 ID 匹配的所有元素和子元素。
例如,如果选择的 ID 为 132,则应删除 ID 为 132、134、136、137、138、139、143 的元素。
到目前为止我尝试的是这样的
Private Function RemoveRecursive(ByRef values As List(Of DataRow), value As String) As List(Of DataRow)
For index As Integer = values.Count - 1 To 0 Step -1
If Not IsDBNull(values(index)("parent")) AndAlso values(index)("parent") = value Then
values.RemoveAt(index)
Return RemoveRecursive(values, value)
value = values(index)("id")
End If
Next
Return values
End Function
根据提供的数据,我假设 133 和 135 也想删除,因为它们是 children 的 131?
实现您想要的目标的一种方法可能是;
- 创建 'tagged' 个条目的空列表
- 遍历列表,如果 ParentID == 131 或 ParentID 在标记条目列表中,则将此节点添加到标记条目
- 从您的原始数据集中删除所有标记的 objects
我试图解决你的问题 (c#):
private static void RemoveRecursive(List<DataRow> values, string valueToRemove) {
DataRow itemToRemove = values.Find(dr => (string)dr["id"] == valueToRemove);
values.Remove(itemToRemove);
IEnumerable<string> children = values.Where(dr => (string)dr["ParentId"] == valueToRemove).Select(dr => (string)dr["id"]);
foreach (string child in children)
RemoveRecursive(values, child);
}
您可以通过以下方式调用此方法:
RemoveRecursive(values, "131");
您还可以添加一些空检查。
离你不远了。您错过了两件事:
- 如果当前行
id
等于搜索值,而不仅仅是parent
。 - 您在对
RemoveRecursive
的内部调用之后设置重估,因此它使用与初始值相同的值,即它每次只会检查132
。
1 号只需要扩展您的 if
语句。对于数字 2,我只是将当前 id 值存储在一个新变量中,然后再删除该行并将其传递给递归调用:
Private Function RemoveRecursive(ByRef values As List(Of DataRow), value As String) As List(Of DataRow)
For index As Integer = values.Count - 1 To 0 Step -1
If Not IsDBNull(values(index)("parent")) AndAlso (values(index)("parent") = value OrElse values(index)("id") = value) Then
Dim newValue as integer = values(index)("id").ToString()
values.RemoveAt(index)
RemoveRecursive(values, newValue)
End If
Next
Return values
End Function
parent / child 的一般示例可能会有所帮助。这是乐观的,因为没有错误检查。请注意,Add 和 Remove 方法都被重载了。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim root As New PC(1)
root.AddChild(1, 10)
root.AddChild(1, 11)
root.AddChild(1, 12)
root.AddChild(11, 110)
root.AddChild(11, 111)
root.AddChild(110, 1100)
root.AddChild(110, 1101)
root.AddChild(1100, 11000)
root.AddChild(1100, 11001)
root.AddChild(1101, 11010)
root.RemoveChild(1100)
End Sub
Class PC 'parent child
Dim myID As Integer
Dim parentPC As PC = Nothing
Dim children As New List(Of PC)
Public Sub New(ID As Integer)
Me.myID = ID
End Sub
Public Function AddChild(parent As Integer, child As Integer) As PC
Dim rv As PC
rv = Me.AddChild(Me, parent, child)
Return rv
End Function
Private Function AddChild(aPC As PC, parent As Integer, child As Integer) As PC
Dim rv As PC
Dim addPC As PC
If aPC.myID = parent Then
addPC = New PC(child)
addPC.children = New List(Of PC)
addPC.parentPC = aPC
aPC.children.Add(addPC)
Return addPC
Else
For Each chld As PC In aPC.children
rv = chld.AddChild(chld, parent, child)
If rv IsNot Nothing Then
Exit For
End If
Next
End If
Return rv
End Function
Public Function RemoveChild(child As Integer) As Boolean
Dim rv As Boolean = False
rv = Me.RemoveChild(child, Me)
Return rv
End Function
Private Function RemoveChild(child As Integer, aPC As PC) As Boolean
Dim rv As Boolean = False
If aPC.myID = child Then
For x As Integer = aPC.children.Count - 1 To 0 Step -1
Dim chld As PC = aPC.children(x)
Me.RemoveChild(chld.myID, chld)
Next
aPC.parentPC.children.Remove(aPC)
aPC.children = Nothing
aPC = Nothing
rv = True
Else
For Each chld As PC In aPC.children
rv = Me.RemoveChild(child, chld)
If rv Then
Exit For
End If
Next
End If
Return rv
End Function
End Class