0

对不起,我觉得我的问题有一个更好的标题,但我想不出。

基本上,情况是这样的:我正在创建一个固定宽度的信息表。我在键列表中有一个 (k,v) 的列表。

完成后,“:”应该居中,并且应该有一个“|” 在最左边和最右边。

我的问题是,我有一些列表太长而无法固定在一行中。我要么需要能够拥有它,以便一旦列表中包含 x 个字符,它将开始一个新行,并将文本缩进到相同的级别,或者我需要能够将多个值编码为这样它们与相同的左侧填充对齐(或者我将拥有内容的“选项卡式”版本。

我到目前为止的一个例子:

def make_information_file(t):
    pairs=[("SERiES","Game of Thrones"),("SiZE","47,196,930,048 bytes"),(AUDiO TRACKS,['English: DTS-HD Master Audio 5.1', 'French: DTS 5.1', 'Spanish: DTS 5.1', 'Polish: DTS 2.0', 'Spanish: DTS 2.0'])]
    general_keys=["COLLECTiON NAME","UPC","RETAiL RELEASE DATE","REGiON","STUDiO"]
    video_keys=["ViDEO","SOURCE","RESOLUTiON","ASPECT RATiO"]
    audio_keys=["AUDiO FORMATS"]
    subtitle_keys=["SUBTiTLES"]
    all_keys=general_keys+video_keys+audio_keys+subtitle_keys
    longest_key=(sorted(all_keys,key=len) or [""])[-1]
    longest_key_length=len(longest_key)
    left_padding=longest_key_length+5
    right_padding=106-left_padding
    empty_left_padding=left_padding+3
    empty_right_padding=106-left_padding-3
    line_formatter=lambda p: "|{field:>{left_padding}} : {value:<{right_padding}}|".format(field=p[0],value=p[-1],left_padding=left_padding,right_padding=right_padding)

现在,请注意,根据最长键的长度,所有内容都对齐,使得“:”位于固定点,其两侧各有一个空格,右侧文本向左对齐,并且这些东西向左对齐。

但是,“AUDiO TRACKS”列表太长,无法放在一行中。如果单词要将其推过它的限制,我可以让它自动拆分(我相信我的偏好,此时第二行(以及之后的任何行)将不得不缩进文本以与第一行保持一致行的文本。另一种选择是拥有它,以便我拥有它,以便每个值都以左侧的 empty_left_padding 为中心,然后是字符串值,然后是足够的空格,以便该行的最终长度是标准的 111 个字符长, 以“|”作为第一个和最后一个字符

desired_output=""""
|                  SERiES : Game of Thrones                                                                   |
|                    SiZE : 47,196,930,048 bytes                                                              |
|           AUDiO FORMATS : English: DTS-HD Master Audio 5.1, French: DTS 5.1, Spanish: DTS 5.1,              |
|                           Polish: DTS 2.0, Spanish: DTS 2.0                                                 |
|                     UPC : 883929191505                                                                      |
|     RETAiL RELEASE DATE : 03-06-2012                                                                        |
|                  REGiON : A, B, C                                                                           |
|                  STUDiO : HBO Home Video                                                                    |
|                   ViDEO : 1080p 1.78:1                                                                      |
|                  SOURCE : BD50                                                                              |
|              RESOLUTiON : 1080p                                                                             |
|            ASPECT RATiO : 16:9                                                                              |"""

所以,我不知道如何处理上面的“音频格式”案例(我对可用的字幕列表有同样的问题)。

4

2 回答 2

3

首先: 将您的信息存储在有序字典中,以保持其顺序,并将数据组织成键值对:

import collections

d = collections.OrderedDict([
    ('SERiES', 'Game of Thrones'),
    ('SiZE', '47,196,930,048 bytes'),
    ('AUDiO FORMATS', 'English: DTS-HD Master Audio 5.1, French: DTS 5.1, Spanish: DTS 5.1, Polish: DTS 2.0, Spanish: DTS 2.0'),
    ('UPC', '883929191505'),
    ('RETAiL RELEASE DATE', '03-06-2012'),
    ('REGiON', 'A, B, C'),
    ('STUDiO', 'HBO Home Video'),
    ('ViDEO', '1080p 1.78:1'),
    ('SOURCE', 'BD50'),
    ('RESOLUTiON', '1080p'),
    ('ASPECT RATiO', '16:9')
])

第二: 您将需要一个文字包装器,以仅包装给定列长度的整个单词:

def word_wrap(string, width=80, indent=4, tab=True):
    output = list()
    for ln in string.replace('\t', ' ' * indent).split('\n'):
        line = list()
        for wd in ln.split(' '):
            if len(' '.join(line) + ' ' + wd) > width:
                output.append(' '.join(line))
                line = list()
            line.append(wd)
        output.append(' '.join(line))
    return [l.replace(' ' * indent, '\t') for l in output] if tab else output

第三: 您需要一个字典格式化程序,您可以在其中设置分隔符,整个文本的宽度,文本之前的填充空间以及分隔符前后的空格:

def format_dict(dictionary, sep=':', width=80, pad=2, pre=1, post=1):
    max_len   = max(len(k) for k in dictionary)
    para_pad  = '%s%s' % ('\n', (pad + max_len + pre + len(sep) + post)*' ')
    separator = '%s%s%s' % (pre*' ', sep, post*' ')
    output = list()
    for key, value in dictionary.iteritems():
        output.append(
            '%s%s%s' % (
                '%s%s' % ((max_len + pad - len(key))*' ', key),
                separator,
                para_pad.join(word_wrap(str(value), width - len(para_pad)))
            )
        )
    return [''.join(l) for l in output]

第四: 修饰段落的左右两侧:

def decorate_para(string, deco='|', width=80):
    output = list()
    for line in string.split('\n'):
        output.append('%s%s%s%s' % (deco, line, (width - len(line))*' ', deco))
    return '\n'.join(output)

第五: 通过打印来测试输出:

w = 79
print decorate_para('\n'.join(format_dict(d, width=w - 2)), width=w)

输出是:

|               SERiES : Game of Thrones                                        |
|                 SiZE : 47,196,930,048 bytes                                   |
|        AUDiO FORMATS : English: DTS-HD Master Audio 5.1, French: DTS 5.1,     |
|                        Spanish: DTS 5.1, Polish: DTS 2.0, Spanish: DTS 2.0    |
|                  UPC : 883929191505                                           |
|  RETAiL RELEASE DATE : 03-06-2012                                             |
|               REGiON : A, B, C                                                |
|               STUDiO : HBO Home Video                                         |
|                ViDEO : 1080p 1.78:1                                           |
|               SOURCE : BD50                                                   |
|           RESOLUTiON : 1080p                                                  |
|         ASPECT RATiO : 16:9                                                   |
于 2013-06-19T10:58:08.117 回答
1

以下是一些可能对您有所帮助的提示:

将您的配对存储为字典。这比使用列表更直观,稍后会派上用场

pairs = dict([("SERiES","Game of Thrones"),("SiZE","47,196,930,048 bytes"),
('AUDiO TRACKS',['English: DTS-HD Master Audio 5.1', 'French: DTS 5.1', 
'Spanish: DTS 5.1', 'Polish: DTS 2.0', 'Spanish: DTS 2.0'])])

要获得键的最大长度,请使用max内置方法:

longest_key = max(pairs.keys(), key=len)
longest_key_length=len(longest_key)

要将字符串向右对齐,请使用字符串函数str.rjust

left_padding = longest_key_length + 5
for k in pairs.keys():
    print '|' + (k + ' : ').rjust(left_padding)

使用字符串函数str.ljust将带有空格的字符串填充为固定值

max_l = 105
max_right = max_l - left_padding 
for k, v in pairs.items():
    left = '|' + (k + ' : ').rjust(left_padding)   
    right = str(v) if len(str(v)) < max_right else ''
    right = right.ljust(max_right) + '|'
    print left + right

最后,您可以使用textwrap库来包装段落或使用更高级的库来处理此类内容

您还可以使用其他字符串方法,如中心、大写、标题...

有了这个,你应该能够让一切顺利进行。

于 2013-06-19T10:33:29.993 回答