我需要将一个分类链接列表精确地输出到html的三列文本中。它们必须与报纸或杂志上的专栏相似。例如,如果总共有20行,第一列和第二列将包含7行,最后一列将包含6行。列表必须是动态的;它将定期更改。
棘手的部分是,链接被分类为一个标题,这个标题不能是“寡妇”。如果你有页面布局背景,你就会知道这意味着标题不能显示在列的底部——它们下面必须至少有一个链接,否则它们应该跳到下一列(我知道,技术上说,如果我真的在做页面布局,应该是两行,但在这种情况下,一行是可以接受的)。我很难弄清楚怎么做。
以下是我的意思的一个例子:
购物链接3链接1
链接1链接4链接2
链接2链接3
连接3节车厢
链接1音乐
游戏链接2链接1
链接1
链接2新闻
如您所见,“新闻”标题位于中间列的底部,“寡妇”也是。这是不能接受的。我可以将它放到下一列,但这会在第二列底部创建不必要的大量空白。相反,需要重新平衡整个列表。
我想知道是否有人有任何技巧来实现这一点,或者源代码或插件。python更好,但任何语言都可以。我只是想把基本概念讲清楚。

最佳答案

一般要点是建立一个包含所有“可流动”项(包括类别)的主列表,然后遍历该列表,根据需要调整每列的行数,这样就不会有任何类别保持寡居(或其他条件)。

Module Module1

    Dim Categories As New Dictionary(Of String, List(Of String))

    Sub Main()

        Const Columns As Integer = 3

        ' create the category items
        Dim ShoppingList As New List(Of String)
        Dim GamesList As New List(Of String)
        Dim CarsList As New List(Of String)
        Dim NewsList As New List(Of String)
        Dim MusicList As New List(Of String)

        ShoppingList.Add("Link1")
        ShoppingList.Add("Link2")
        ShoppingList.Add("Link3")

        GamesList.Add("Link1")
        GamesList.Add("Link2")
        GamesList.Add("Link3")
        GamesList.Add("Link4")

        CarsList.Add("Link1")
        CarsList.Add("Link2")

        NewsList.Add("Link1")
        NewsList.Add("Link2")
        NewsList.Add("Link3")

        MusicList.Add("Link1")

        ' create the categories
        Categories.Add("Shopping", ShoppingList)
        Categories.Add("Games", GamesList)
        Categories.Add("Cars", CarsList)
        Categories.Add("News", NewsList)
        Categories.Add("Music", MusicList)

        ' count each category and its items
        Dim TotalRows As Integer = Categories.Count
        For Each kvp As KeyValuePair(Of String, List(Of String)) In Categories
            TotalRows += kvp.Value.Count
        Next

        ' add a space between each category
        TotalRows += (Categories.Count - 1)

        ' determine the number of rows per column
        Dim RowsPerColumn As Integer = Int(TotalRows / Columns) + If((TotalRows Mod Columns) > 0, 1, 0)

        ' build a master list
        Dim master As New List(Of String)
        For Each kvp As KeyValuePair(Of String, List(Of String)) In Categories
            master.Add(kvp.Key)
            For Each item As String In kvp.Value
                master.Add(item)
            Next
            master.Add(" ")
        Next

        ' remove the last invalid blank item
        master.RemoveAt(master.Count - 1)

        ' ensure that the RowsPerColumn'th-item in the list is not a category
        Dim adjusted As Boolean
        Do
            adjusted = False
            For i As Integer = 1 To master.Count - 1 Step RowsPerColumn - 1
                If Categories.Keys.Contains(master(i)) Then
                    RowsPerColumn += 1 ' adjust rows per column (could go up or down)
                    adjusted = True
                End If
            Next
        Loop While adjusted

        ' output resulting table
        Using sw As New IO.StreamWriter("test.htm")
            sw.WriteLine("<html>")
            sw.WriteLine("<body>")
            sw.WriteLine("<table cellspacing=""0"" cellpadding=""3"" border=""1"">")
            For j As Integer = 0 To RowsPerColumn - 1
                sw.WriteLine("<tr>")
                Dim columnCount As Integer = 0 ' columns written
                For i As Integer = j To master.Count - 1 Step RowsPerColumn
                    sw.WriteLine("<td>" & master(i) & "</td>")
                    columnCount += 1
                Next
                ' if the number of columns actually written was less than Columns constant
                If columnCount < Columns Then
                    For c As Integer = 0 To Columns - columnCount - 1
                        sw.WriteLine("<td>&nbsp;</td>")
                    Next
                End If
                sw.WriteLine("</tr>")
            Next
            sw.WriteLine("</table>")
            sw.WriteLine("</body>")
            sw.WriteLine("</html>")
        End Using

    End Sub

End Module

10-04 10:22