如何在Python表中使用multirow单元格?

问题描述 投票:1回答:1

我正在尝试创建一个简单的Python表类,它接受列表作为内容列表,然后构建一个可以打印到终端的表字符串表示。我想要的一个功能是在表格的单元格中包装文本。

我很高兴使用模块textwrap来确定适当的文本包装。

基本上,对于以下内容

[
    ["heading 1", "heading 2"],
    ["some text", "some more text"],
    ["lots and lots and lots and lots and lots of text", "some more text"]
]

我想要一个生成的表示,如下所示:

-------------------------------
|heading 1     |heading 2     |
-------------------------------
|some text     |some more text|
-------------------------------
|lots and lots |some more text|
|and lots and  |              |
|lots and lots |              |
|of text       |              |
-------------------------------

我的问题是:如果给出由textwrap确定的文本包装的列表表示,我如何实现多行单元格?

我的代码如下:

import textwrap
import subprocess

def terminalWidth():
    return(
        int(
            subprocess.Popen(
                ["tput", "cols"],
                stdout = subprocess.PIPE
            ).communicate()[0].decode("utf-8").strip("\n")
        )
    )

class Table(object):

    def __init__(
        self,
        content         = None,
        widthTable      = None,
        columnDelimiter = "|",
        rowDelimiter    = "-"
        ):
        self.content    = content
        if widthTable is None:
            self.widthTable = terminalWidth()
        self.columnDelimiter = columnDelimiter
        self.rowDelimiter = rowDelimiter

    def value(self):
        self.numberOfColumns = len(self.content[0])
        self.widthOfColumns =\
            self.widthTable / self.numberOfColumns -\
            self.numberOfColumns * len(self.columnDelimiter)
        self.tableString = ""
        for row in self.content:
            for column in row:
                self.tableString =\
                    self.tableString +\
                    self.columnDelimiter +\
                    textwrap.wrap(column, self.widthOfColumns)
            self.tableString =\
                self.tableString +\
                self.columnDelimiter +\
                "\n" +\
                self.widthTable * self.rowDelimiter +\
                "\n" +\
        return(self.tableString)

    def __str__(self):
        return(self.value())

def main():

    table1Content = [
        ["heading 1", "heading 2"],
        ["some text", "some more text"],
        ["lots and lots and lots and lots and lots of text", "some more text"]
    ]

    table1 = Table(
        content    = table1Content,
        widthTable = 15
    )

    print(table1)

if __name__ == '__main__':
    main()
python textwrapping
1个回答
2
投票

这是一个做你想要的课程:

import textwrap

class Table:

    def __init__(self,
                 contents,
                 wrap,
                 wrapAtWordEnd = True,
                 colDelim = "|",
                 rowDelim = "-"):

        self.contents = contents
        self.wrap = wrap
        self.colDelim = colDelim
        self.wrapAtWordEnd = wrapAtWordEnd

        # Extra rowDelim characters where colDelim characters are
        p = len(self.colDelim) * (len(self.contents[0]) - 1)

        # Line gets too long for one concatenation
        self.rowDelim = self.colDelim
        self.rowDelim += rowDelim * (self.wrap * max([len(i) for i in self.contents]) + p)
        self.rowDelim += self.colDelim + "\n"

    def withoutTextWrap(self):

        string = self.rowDelim

        for row in self.contents:
            maxWrap = (max([len(i) for i in row]) // self.wrap) + 1
            for r in range(maxWrap):
                string += self.colDelim
                for column in row:
                    start = r * self.wrap
                    end = (r + 1) * self.wrap 
                    string += column[start : end].ljust(self.wrap)
                    string += self.colDelim
                string += "\n"
            string += self.rowDelim

        return string

    def withTextWrap(self):

        print(self.wrap)

        string = self.rowDelim

        # Restructure to get textwrap.wrap output for each cell
        l = [[textwrap.wrap(col, self.wrap) for col in row] for row in self.contents]

        for row in l:
            for n in range(max([len(i) for i in row])):
                string += self.colDelim
                for col in row:
                    if n < len(col):
                        string += col[n].ljust(self.wrap)
                    else:
                        string += " " * self.wrap
                    string += self.colDelim
                string += "\n"
            string += self.rowDelim

        return string

    def __str__(self):

        if self.wrapAtWordEnd:

            return self.withTextWrap() 

        else:

            return self.withoutTextWrap()

if __name__ == "__main__":

    l = [["heading 1", "heading 2", "asdf"],
         ["some text", "some more text", "Lorem ipsum dolor sit amet."],
         ["lots and lots and lots and lots and lots of text", "some more text", "foo"]]

    table = Table(l, 20, True)

    print(table)

withTextWrap()使用您提到的textwrap模块,并利用其输出来构建表格表示。在玩这个的时候,我也提出了一种做你想做的事情(差不多)的方法,没有textwrap模块,你可以在withoutTextWrap()方法中看到。我说“差不多”因为textwrap模块在一个单词的末尾正确地打破了行,而我的方法在包装点直接打破了字符串。

因此,如果您创建第三个构造函数参数设置为True的表,则使用textwrap模块,该模块将生成此输出:

|--------------------------------------------------------------|
|heading 1           |heading 2           |asdf                |
|--------------------------------------------------------------|
|some text           |some more text      |Lorem ipsum dolor   |
|                    |                    |sit amet.           |
|--------------------------------------------------------------|
|lots and lots and   |some more text      |foo                 |
|lots and lots and   |                    |                    |
|lots of text        |                    |                    |
|--------------------------------------------------------------|

如果那个论点是False,则称为非textwrap版本:

|--------------------------------------------------------------|
|heading 1           |heading 2           |asdf                |
|--------------------------------------------------------------|
|some text           |some more text      |Lorem ipsum dolor si|
|                    |                    |t amet.             |
|--------------------------------------------------------------|
|lots and lots and lo|some more text      |foo                 |
|ts and lots and lots|                    |                    |
| of text            |                    |                    |
|--------------------------------------------------------------|

希望这可以帮助。

© www.soinside.com 2019 - 2024. All rights reserved.