自动对齐“表格式”Python代码

时间:2011-10-04 03:59:22

标签: python

我有一些看起来像这样的Python代码:

rates = {3: [((17500, 99999), Decimal('23425.00'), Decimal('7234.24'))],
         4: [((    0,  3510), Decimal( '4563.00'), Decimal('5234.00')),
             (( 3510, 17500), Decimal('34578.00'), Decimal('3464.50')),
             ((17500, 99999), Decimal('18268.00'), Decimal('5734.66'))],
         5: [((17500, 99999), Decimal('83564.00'), Decimal('3475.60'))]}

请注意,十进制值在小数点周围对齐,而整数是右对齐的。

是否有某些软件能够以自动化方式执行此类复杂对齐?我会对任何接近的东西感兴趣,即使它与上述不完全匹配。

5 个答案:

答案 0 :(得分:5)

注意:我不认为以下内容特别明智。)

在大多数情况下,如果您只是输入(大多数编辑将帮助您调整您的词典和列表项目)您的原始代码,您应该得到这样的内容:

rates = {3: [((17500, 199999), Decimal('23425.00'), Decimal('7234.245'))],
         4: [((0, 3510), Decimal('4563.00'), Decimal('5234.00')),
             ((3510, 17500), Decimal('34578.00'), Decimal('464.50')),
             ((17500, 99999), Decimal('18268.00'), Decimal('5734.66'))],
         15: [((17500, 99999), Decimal('83564.00'), Decimal('3475.60'))]}

(我已经做了一些更长的值,有些更短,以增加更多的怪癖。)

使用Vim的Tabular插件,在上面的代码中按顺序执行以下命令(您可能希望以可视方式阻止它)将以匹配的方式格式化上述代码你原来的问题:

:Tab /^[^[(]*\zs[[(]/l0
:Tab /^[^(]*\zs(/l0
:Tab /(\zs\d\+\s*,/l0r1
:Tab /,\s*\zs\d\+)/l1r0
:Tab /['"]\d*\ze\.\d*['"]/l0r0

操作是:

  1. 对齐第一个[( s。
  2. 对齐第一个(,这样可以解决第一个操作中的错位。
  3. 右对齐(17500,上的,类似值。
  4. 右对齐, 99999)上的,类似值。
  5. 对齐'4563.00'上的.类似值。
  6. 您可以制作用于普通和可视模式的映射:

    noremap <leader>ff :Tab /^[^[(]*\zs[[(]/l0<CR>
                      \:Tab /^[^(]*\zs(/l0<CR>
                      \:Tab /(\zs\d\+\s*,/l0r1<CR>
                      \:Tab /,\s*\zs\d\+)/l1r0<CR>
                      \:Tab /['"]\d*\ze\.\d*['"]/l0r0<CR>
    

    最终结果:

    rates = {3:  [((17500, 199999), Decimal('23425.00'), Decimal('7234.245'))],
             4:  [((    0,   3510), Decimal( '4563.00'), Decimal('5234.00')),
                  (( 3510,  17500), Decimal('34578.00'), Decimal( '464.50')),
                  ((17500,  99999), Decimal('18268.00'), Decimal('5734.66'))],
             15: [((17500,  99999), Decimal('83564.00'), Decimal('3475.60'))]}
    

    显然,这些操作的有效性取决于代码的结构和原始格式,但希望这会激发你的灵感。

答案 1 :(得分:2)

虽然标准库pprint模块将添加空格以使字典和列表在屏幕上至少看起来合理,但我知道没有什么可以,例如,考虑字符串常量中的句点是重要的并添加足够的空格来对齐它们!除非我错了,否则你可能总是手工在Python中进行这种对齐。

如果将这些值存储在纯文本的单独表文件中,当然,您可能会找到几个愿意帮助您对齐小数点的编辑器。

答案 2 :(得分:2)

我遇到了同样的问题。管理层希望以某种表格格式从数据打印出漂亮的报告。

我不想只是用一些带有“魔术”空间的打印语句来修复对齐,所以我想出了这个python函数:

def column(filename, data, indent=0):
    """This function takes a list of lists and produces columized output"""
    # get the width of the columns
    width = []
    for mylist in data:
        for count, d in enumerate(mylist):
            if count > (len(width)-1):
                width.append(len(str(d)))
            elif len(str(d)) > width[count]:
                width[count] = len(str(d))
    # print the data
    for mylist in data:
        line = '{0:<{indent}}'.format('', indent=indent)    
        for count, d in enumerate(mylist):
            try:
                line = '%s%s' % (line, '{0:{w},} '.format(d, w=width[count]))
            except ValueError, e:
                line = '%s%s' % (line, '{0:{w}} '.format(d, w=width[count]))
        filename.write(line)
        filename.write('\n')

它并不完美,你需要调整它以产生你想要的输出。最具体地说,它目前需要一个列表,因为我想传递一个特定的顺序,并且不会对字典进行排序。

答案 3 :(得分:2)

这是一个代码,可以做你想要的,AFAIU。

它主要是人为的,因为它只适用于精确字典的形状 但是,我确信它是一个可以改进的基础,可以考虑其他规范,例如每个元组中的几个Decimal实例。

from decimal import Decimal


rates = {3:  [((   500,   999), Decimal('23425.008'), Decimal('   4.24245'))],
         281: [((     0,    10), Decimal( '4563.00' ), Decimal('  34.00'   )),
              ((  3510,   500), Decimal('  578'    ), Decimal(' 464.503'  )),
              ((174500,    19), Decimal('   68.2'  ), Decimal('5734'      ))],
         54:  [(( 93500, 99999), Decimal(' 1564.44' ), Decimal('  75.60'   ))]}



def complex_display(di):
    K,I1,I2,D1B,D1P,D2B,D2P = [],[],[],[],[],[],[]

    for key,val in di.iteritems():
        K.append(len(str(key)))
        for (i,j),d1,d2 in val :
            I1.append(len(str(i)))
            I2.append(len(str(j)))
            d1b,d1p = str(d1).split('.') if '.' in str(d1) else (str(d1),'.')
            d2b,d2p = str(d2).split('.') if '.' in str(d2) else (str(d2),'.')
            D1B.append(len(d1b))
            D1P.append(len(d1p))
            D2B.append(len(d2b))
            D2P.append(len(d2p))

    k   = '%%%dd: [' % max(K)
    fv = "%%s((%%%ds, %%%ds), Decimal('%%%ds.%%-%ds'), Decimal('%%%ds.%%-%ds'))%%s" % (max(I1),max(I2),max(D1B),max(D1P),max(D2B),max(D2P))

    def produce(di):
        for key,val in sorted(di.iteritems()):
            for n,((i,j),d1,d2) in enumerate(val) :
                d1b,d1p = str(d1).split('.') if '.' in str(d1) else (str(d1)[0:-2],"")
                d2b,d2p = str(d2).split('.') if '.' in str(d2) else (str(d2)[0:-2],"")
                yield fv % ('      ' if n else k % key,i,j,d1b,d1p,d2b,d2p,']' if n+1==len(val) else '')

    return '\n'.join(produce(di))

结果

  3: [((   500,   999), Decimal('23425.008'), Decimal('   4.24245'))]
 54: [(( 93500, 99999), Decimal(' 1564.44 '), Decimal('  75.60   '))]
281: [((     0,    10), Decimal(' 4563.00 '), Decimal('  34.00   '))
      ((  3510,   500), Decimal('    5.   '), Decimal(' 464.503  '))
      ((174500,    19), Decimal('   68.2  '), Decimal('  57.     '))]

没有两个字符'{'和'}',为了一个微弱的结果添加它们要复杂得多。如果你想要的话,我让你完成代码添加它们

结果按键排序。

答案 4 :(得分:0)

使用您认为合适的任何对齐方式编写一些代码来漂亮地打印您的代码是相当简单的;但你必须告诉它要寻找什么。

当你手工编写出来时,你会在不考虑它的情况下做出很多风格决定,但是如果你想让程序做同样的格式化,你必须明确地做出这些风格决定。例如,您已决定垂直对齐括号,同时将包含9个元素的列表对齐,就好像它实际上是3个3个组一样,同时完全忽略每个元素嵌套的级别。

这样的对齐布局实际上只对你提供的列表有意义,而不是一般意义上的,所以你不会像其他人那样从别人那里找到预制代码。 。但显然这并不代表你自己不能做到。