在Python中将列表转换为HTML表格的最简单方法是什么?

36

假设我有一个列表,如下所示:

['one','two','three','four','five','six','seven','eight','nine']

我想尝试将这些数据转换为不同维度的HTML表格:

one     two    three
four    five   six
seven   eight  nine
或者
one    four   seven
two    five   eight
three  six    nine
或。
one    two   three  four
five   six   seven  eight
nine

有没有一个库可以处理这个问题而不需要进行疯狂的列表拼接或嵌套的for循环?我的谷歌搜索结果显示有一些HTML库,但我没有时间逐个检查它们是否可以很好地处理表格。有没有人曾经遇到过这种情况?如果有,你是怎么做的?

7个回答

53

使用tabulate

from tabulate import tabulate

table = [['one','two','three'],['four','five','six'],['seven','eight','nine']]

print(tabulate(table, tablefmt='html'))

它会产生以下输出。

<table>
<tbody>
<tr><td>one  </td><td>two  </td><td>three</td></tr>
<tr><td>four </td><td>five </td><td>six  </td></tr>
<tr><td>seven</td><td>eight</td><td>nine </td></tr>
</tbody>
</table>

3
不错,我还可以补充一下,PrettyTable也是另一个不错的选择。 - Han.Oliver
1
最简单、代码行数最少的方法应该是最佳答案。 - msarafzadeh
太棒了!伟大的项目。 - fedorqui
但这并不允许这种"实验"。 - undefined

40

我会将您的问题分解为两部分:

  • 给定一个“平面列表”,生成一个子列表的列表,其中子列表具有给定的长度,并且整个列表可以按照行或列的方式遍历 (您的第一个和第三个示例是行主序,您的第二个示例是列主序);
  • 给定一个由字符串项组成的子列表列表,将其转换为HTML表格。

我认为这两个任务确实非常不同,将它们混合在一起没有任何好处(而且很容易出错),所以我会惊讶地发现任何设计良好的库会这样做。

对于第1点,行主序很容易:

def row_major(alist, sublen):      
  return [alist[i:i+sublen] for i in range(0, len(alist), sublen)]

而且列主序也不那么糟糕:

def col_major(alist, sublen):
  numrows = (len(alist)+sublen-1) // sublen 
  return [alist[i::sublen] for i in range(numrows)]
例如...:
L = ['one','two','three','four','five','six','seven','eight','nine']
for r in row_major(L, 3): print r
print
for r in col_major(L, 3): print r
for r in row_major(L, 4): print r

生成你所需的三个结果(每行一个列表,尚未以HTML形式呈现)。

问题的后半部分 - 从字符串列表的列表生成HTML表格:

def html_table(lol):
  print '<table>'
  for sublist in lol:
    print '  <tr><td>'
    print '    </td><td>'.join(sublist)
    print '  </td></tr>'
  print '</table>'
如果您希望将其作为单个字符串而不是打印出来,请将每个print更改为yield并使用'\n'.join(html_table(lol))
现在您有两个简单、有用、可用和可重复使用的构建块——将它们分开将在您想要将数据呈现为除HTML表以外的任何形式时非常方便,以及无论以任何其他方式构建要呈现为HTML表的列表,都很容易。将它们组合在一起在应用程序代码中很容易实现,但当然也可以进行简单的“粘合例程”,例如假设基于yield版本的html_table并且需要单个字符串结果:
def list_to_html_table(alist, sublength, column_major=False):
  if column_major:
    lol = col_major(alist, sublength)
  else:
    lol = row_major(alist, sublength)
  return ''.join(html_table(lol))

相比于使用纠缠在一起的代码块编程,这种基础模块的方法难道不是更美好、更令人愉悦、更高效吗?-)


你能展示一下如何在一个字符串的列表中使用yield,例如[['e1','f1'],['e2','f2']]。你需要一个返回值。 - Timo

11

仅供参考,我实现了一个名为simpletable的小型Python模块,可提供简单的HTML表格生成功能。它还可以处理此问题中描述的问题。

使用方法如下:

import simpletable

test_data = [str(x) for x in range(20)]
formatted_data = simpletable.fit_data_to_columns(test_data, 5)
table = simpletable.SimpleTable(formatted_data)
html_page = simpletable.HTMLPage(table)
html_page.save("test_page.html")

由于它不需要第三方包,您可以从我的存储库获取代码并在您的项目中使用。


7

另一个选择是prettytable:

from prettytable import PrettyTable
pt = PrettyTable()

如果你想要生成 HTML 格式:

print(pt.get_html_string())

如果只生成 ASCII 格式的表格:

print(pt.get_string())

请参考官方文档:https://ptable.readthedocs.io/en/latest/tutorial.html,了解更多选项,例如启用不同的样式。

祝使用愉快。


正是我所需要的。(我需要将对象列表打印到HTML表格中以便发送电子邮件) - takanuva15

2

有许多与模板相关的库可供选择(我喜欢Genshi,但还有许多其他库)。

或者你可以尝试这样做:

def print_table(data, row_length):
    print '<table>'
    counter = 0
    for element in data:
        if counter % row_length == 0:
            print '<tr>'
        print '<td>%s</td>' % element
        counter += 1
        if counter % row_length == 0:
            print '</tr>'
    if counter % row_length != 0:
        for i in range(0, row_length - counter % row_length):
            print '<td>&nbsp;</td>'
        print '</tr>'
    print '</table>'

OP希望避免嵌套的for循环。因此,可能需要介绍map(lambda)的使用方法。 - whatnick
4
你能看到一个循环里面还有另一个循环吗?我没有看到。 - Tom Leys

0

虽然这个问题以前已经有人回答过了,但是我想用numpypandas DataFrame提供另一种解决方案。由于现在很多人对数据科学感兴趣,我认为使用pandas来解决这个问题会很有趣:

GITHUB解决方案:
我已经将我的解决方案放在了我的GitHub存储库中,您也可以在Google Colaboratory中运行和探索它(我强烈推荐这样做)。

我在这里使用的自定义函数generate_html_with_table())在这个Jupyter Notebook中可用。

解决方案:
要获得您的解决方案,请运行以下命令:

data = ['one','two','three','four','five','six','seven','eight','nine']
columns = 4                   # Number of Columns
columns_or_rows = columns
column_name_prefix = 'Column' # Prefix for Column headers
span_axis = 1                 # Span along a row (1) or a column (0) first
showOutput = True             # Use False to suppress printing output

# Generate HTML
data_html, data_df = generate_html_with_table(data, columns_or_rows, column_name_prefix, span_axis, showOutput)

输出:

HTML Generated: 

<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Column_0</th>
      <th>Column_1</th>
      <th>Column_2</th>
      <th>Column_3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>one</td>
      <td>two</td>
      <td>three</td>
      <td>four</td>
    </tr>
    <tr>
      <th>1</th>
      <td>five</td>
      <td>six</td>
      <td>seven</td>
      <td>eight</td>
    </tr>
    <tr>
      <th>2</th>
      <td>nine</td>
      <td></td>
      <td></td>
      <td></td>
    </tr>
  </tbody>
</table>

在一行中跨度输出代码


0

或许对于玩具代码来说,操纵模板更容易一些,=p

def get_html_tbl(seq, col_count):
    if len(seq) % col_count:
        seq.extend([''] * (col_count - len(seq) % col_count))
    tbl_template = '<table>%s</table>' % ('<tr>%s</tr>' % ('<td>%s</td>' * col_count) * (len(seq)/col_count))
    return tbl_template % tuple(seq)

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