【问题标题】:Using rjust() and reducing for loops in Python在 Python 中使用 rjust() 并减少 for 循环
【发布时间】:2019-01-26 22:59:52
【问题描述】:

我正在尝试制定一个接受字符串列表列表的函数 并将其显示在一个组织良好的表格中,每列右对齐。 假设所有内部列表将包含相同数量的字符串。 例如,该值可能如下所示:

tableData = [['apples', 'oranges', 'cherries', 'banana'],

['Alice', 'Bob', 'Carol', 'David'],

['dogs', 'cats', 'moose', 'goose']]

您的函数将打印以下内容(右对齐):

    apples Alice   dogs

   oranges   Bob   cats

  cherries Carol  moose

    banana David  goose

使用给定的提示,我已经到达:

def printable(tableData):
    newTable = np.zeros((len(tableData[0]),len(tableData)))
    colWidths = [0] * len(tableData)
    for i in range(0,len(tableData)):
        colWidths[i] = max(tableData[i], key=len)
    largest = max(colWidths, key=len)
    for i in range(0,len(tableData)):
        for j in range(0,len(tableData[0])):
            newTable[i][j] = tableData[j][i].rjust(len(largest))

我对没有感到震惊。的 for 循环。作为一个初学者,我仍然摆脱了“for-loop”模式。另外,我正在考虑解决这个问题的最佳攻击形式。谢谢。

【问题讨论】:

    标签: python arrays string for-loop


    【解决方案1】:

    这是在普通 Python 中执行此操作的一种方法。我们使用zip来转置表格,这样我们就可以得到每列的最大宽度。

    table_data = [
        ['apples', 'oranges', 'cherries', 'banana'],
        ['Alice', 'Bob', 'Carol', 'David'],
        ['dogs', 'cats', 'moose', 'goose'],
    ]
    
    # Determine the width of each column
    widths = [max(map(len, column)) for column in zip(*table_data)]
    new_table = [[s.rjust(w) for s, w in zip(row, widths)]
        for row in table_data]
    
    for row in new_table:
        print(row)
    

    输出

    ['apples', 'oranges', 'cherries', 'banana']
    [' Alice', '    Bob', '   Carol', ' David']
    ['  dogs', '   cats', '   moose', ' goose']
    

    如果您真的不需要新的 2D 列表,而只想打印数据,可以执行以下操作:

    for row in table_data:
        print(*(s.rjust(w) for s, w in zip(row, widths)))
    

    输出

    apples oranges cherries banana
     Alice     Bob    Carol  David
      dogs    cats    moose  goose
    

    这是一个转换表格的新版本。

    widths = [max(map(len, row)) for row in table_data]
    new_table = [[s.rjust(w) for s, w in zip(row, widths)] for row in zip(*table_data)]
    for row in new_table:
        print(row)
    

    输出

    ['  apples', 'Alice', ' dogs']
    [' oranges', '  Bob', ' cats']
    ['cherries', 'Carol', 'moose']
    ['  banana', 'David', 'goose']
    

    【讨论】:

    • zip 正是我在玩弄的 :) 谢谢!
    • 我刚刚注意到输出与所需的不一样?现在正在努力。
    • @db18 好的。我看到您希望输出转置。 :oops: 我会添加一个新版本。
    • 每当我看到最后一个用于打印的for 循环:collections.deque((print(row) for row in new_table), maxlen=0) 时,我都会有这样的冲动。不过我不积极推荐它:)
    • @MadPhysicist 对于我的私人用途,我很想使用print(*map(' '.join, new_table), sep='\n'),但我尽量让事情变得更简单。 ;)
    【解决方案2】:

    to_stringindex=Falsetransposesplitlines 的 Pandas 组合

    有一个header=None 选项,但由于某种未知原因,它弄乱了对齐方式。所以我留下标题并用splitlines[1:] 关闭它

    import pandas as pd
    print('\n'.join(pd.DataFrame(table_data).T.to_string(index=False).splitlines()[1:]))
    
      apples  Alice   dogs
     oranges    Bob   cats
    cherries  Carol  moose
      banana  David  goose
    

    f 字符串 + str.format

    构造一个基于最大字符串长度的str.format 函数。
    灵感来自PM 2Ring

    f = '  '.join([f"{{:>{max(map(len, r))}}}" for r in table_data]).format
    print('\n'.join([f(*t) for t in zip(*table_data)]))
    
      apples  Alice   dogs
     oranges    Bob   cats
    cherries  Carol  moose
      banana  David  goose
    

    详情

    这个:

    '  '.join([f"{{:>{max(map(len, r))}}}" for r in table_data])
    

    产生一个如下所示的字符串:

    '{:>8}  {:>5}  {:>5}'
    

    8, 5, 5 是每行的最大字符串长度。我通过在末尾附加 .format 将其转换为格式函数。它现在是一个接受 3 个位置参数并按规定间距格式化字符串的函数。

    【讨论】:

      【解决方案3】:

      我以为你必须自己编写算法,但在你的尝试中你使用了numpy,所以我假设你也可以使用pandas

      您可以将数据加载到数据框中,转置并使用 pandas DataFrame 类中已构建的 __repr__

      换句话说,

      pd.DataFrame(arr).T.__repr__()
      

      产生

      '          0      1      2\n0    apples  Alice   dogs\n1   oranges    Bob   cats\n2  cherries  Carol  moose\n3    banana  David  goose'
      

      这样,如果你print它,你会得到

                0      1      2
      0    apples  Alice   dogs
      1   oranges    Bob   cats
      2  cherries  Carol  moose
      3    banana  David  goose
      

      如果您不想打印列 ID,可以使用 __repr__ 输出

      print('\n'.join([x[1:] for x in df.__repr__().split('\n')[1:]]))
      
      
          apples  Alice   dogs
         oranges    Bob   cats
        cherries  Carol  moose
          banana  David  goose
      

      【讨论】:

        【解决方案4】:
        tableData = [
            ['apples', 'oranges', 'cherries', 'banana'],
            ['Alice', 'Bob', 'Carol', 'David'],
            ['dogs', 'cats', 'moose', 'goose']
        ]
        
        # Determine maximum column width
        colWidth = 0
        for x in tableData:
            colWidth = max(colWidth, len(max(x, key=len)))
        
        # Use zip to "flip" your rows and columns
        # Note that the * first unpacks your list of lists 
        
        for row in zip(*tableData):
             # Join each row element together into a string, right justifying each element to your column width as you go
            print ''.join([ele.rjust(colWidth) for ele in row])
        

        【讨论】:

          猜你喜欢
          • 2017-07-22
          • 2016-10-13
          • 2011-05-16
          • 1970-01-01
          • 2016-10-17
          • 2016-12-30
          • 2013-10-21
          • 2011-12-22
          • 2011-10-29
          相关资源
          最近更新 更多