在VB asp.net 2.0中对数据表的行进行分组

3

如其名,我正在尝试在数据表中对行进行分组。更详细地说,这个表具有相同的行,除了一个字段(列)之外。基本上,我想做的是将相同行的所有不同字段放入单个字段中,同时删除其他行。

这是我目前正在使用的语法:

   Dim i As Integer
    Dim j As Integer
    For i = 0 To (ds.Tables(0).Rows.Count() - 1) Step 1
        If (i < ds.Tables(0).Rows.Count()) Then
            roleHtml = "<table><tr><td>" + ds.Tables(0).Rows(i).Item("roleName") + "</td></tr>"
            For j = (ds.Tables(0).Rows.Count() - 1) To 0 Step -1
                If (ds.Tables(0).Rows(i).Item("UserName") = ds.Tables(0).Rows(j).Item("UserName")) And (ds.Tables(0).Rows(i).Item("roleName") IsNot ds.Tables(0).Rows(j).Item("roleName")) Then
                    roleHtml += "<tr><td>" + ds.Tables(0).Rows(j).Item("roleName") + "</td></tr>"
                    ds.Tables(0).Rows.Remove(ds.Tables(0).Rows(j))
                    i -= 1
                End If
            Next j
            roleHtml += "</table>"
            ds.Tables(0).Rows(i).Item("roleName") = roleHtml
        End If
    Next i

问题在于删除行后,它们的索引会改变,导致该字段被扔到另一行中,与其无关。
5个回答

1

好的,我可以帮你处理循环结构。虽然这个方法不完全符合你现在的需求(它会保留原始表格并且只是构建一个大字符串,同时也假设表格已按照特定方式排序),但它可以演示如何使用你的实际数据进行经典的控制中断处理。为了让这个方法生效,表格需要按照用户和角色进行排序。

Dim i As Integer = 0
Dim CurUser As String = ""
Dim CurRole As String = ""
Dim result As new StringBuilder()
Dim r as DataRowCollection = ds.Tables(0).Rows

While i < r.Count
    'Next User:'
    CurUser = r(i)("UserName")
    result.AppendFormat("<h2>{0}</h2>", CurUser).AppendLine()
    result.AppendLine("<table>")

    While i < r.Count AndAlso CurUser = r(i)("UserName")
        'Next Role:'
        CurRole = r(i)("roleName")
        result.AppendFormat("<tr><td>{0}</td></tr>", CurRole).AppendLine()

        While i < r.Count AndAlso CurUser = r(i)("UserName") AndAlso CurRole = r(i)("roleName")
            i += 1 'Next Record: same user, role '
        End While
        'Finished this role'
    End While
    'Finished this user:'
     result.AppendLine("</table>").AppendLine()
End While

这个程序有3个嵌套循环,而不是你通常看到的两个。然而,它仍然具有线性性能:它只会对每个记录进行一次迭代。这是因为所有的循环都共享同一个计数器,该计数器仅在内部循环中递增,并且它们都具有相同的基本结束条件。


好的,伙计,稍后我会检查它。 - Drahcir

0

最近我也需要做一个类似于 控制中断 风格的报告。

我最终将数据绑定到了一个 Repeater 控件上,其中项模板只是一个 Literal 控件。然后我处理了 OnItemDataBound 事件,并有一些代码,大致类似于你的代码,检查只要“控制”(在控制中断意义上而不是 Web 控件意义上)列匹配,就将剩余列的值添加到类级变量中,并将 e.Item.Visible 设置为 false。当它们不再匹配时,我将 e.Item.Visible 保持为 true(默认值),并将文本控件的 Text 属性设置为我正在处理的行所需的 HTML。

我相信有更好的方法来完成这个任务,但是在 asp.net 中查找控制中断报告的信息并不容易:在这个领域搜索时,control 这个词具有双重含义,很难克服。


请注意,我真的不喜欢我编写代码的方式,因为它是一个嵌套循环,会消耗很多性能。我想也许有一个更简单的解决方案。 - Drahcir

0

这段代码很难读懂,通常意味着需要进行一些重构。

你能详细说明一下你想要实现什么吗?你希望在你的DataTable中保留什么?

数据是否已经排序或者你可以在数据库中进行排序?如果已经排序,那么你只需要通过单个循环即可。

我会按照以下步骤进行:

  • 对datatable进行排序
  • 为你的结果创建一个新的datatable
  • 按顺序遍历,保持上一个用户名和当前角色列表的变量。如果用户名与上一个不同,则向你的datatable添加一个新行,其中包含上一个用户名和当前角色列表。如果用户名相同,则将其附加到角色列表中。别忘了在到达结尾时添加最后一行。

这样可以避免从你正在遍历的集合中删除行的问题。


我会上传一个我想要实现的图表,但目前我正在工作,无法浏览图像托管网站。 - Drahcir

0

看起来我的代码可以工作了。i -=1 这一行是多余的。对于造成的任何不便,我很抱歉,并感谢您的帮助。


如果数据已经排序,请查看我的代码。它利用排序以获得线性性能,而不是n平方或n log(n)。 - Joel Coehoorn

0

循环部分看起来好像已经搞定了。

但是在循环时有选择性地删除项(或全部删除),如果你没有意识到关键是从底部向上工作(或者从最后一个元素向前,或者以任何你想表达的方式),那么这个过程会变得非常麻烦。

这就是删除问题的整个答案。

当你从后往前工作时,在编号列表中删除一个项目只会影响你已经处理过的项目的索引 - 谁在乎呢?

-T。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接