我需要将一个分类链接列表精确地输出到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> </td>")
Next
End If
sw.WriteLine("</tr>")
Next
sw.WriteLine("</table>")
sw.WriteLine("</body>")
sw.WriteLine("</html>")
End Using
End Sub
End Module