【问题标题】:Formatting a list of text into columns将文本列表格式化为列
【发布时间】:2010-09-15 08:38:04
【问题描述】:

我正在尝试将字符串值列表输出为 2 列格式。将字符串列表转换为“普通文本”的标准方法是使用 string.join 方法。但是,它只需要 2 个参数,所以我只能使用“\n”创建一个列。我认为尝试创建一个只需在列之间添加一个选项卡的循环就可以了,但逻辑无法正常工作。

我找到了一个 ActiveState page,它的操作方式相当复杂,但它是 4 年前的。现在有简单的方法吗?


编辑这是我要使用的列表。

skills_defs = ["ACM:Aircraft Mechanic", "BC:Body Combat", "BIO:Biology",
    "CBE:Combat Engineer", "CHM:Chemistry", "CMP:Computers", 
    "CRM:Combat Rifeman", "CVE:Civil Engineer", "DIS:Disguise",
    "ELC:Electronics","EQ:Equestrian", "FO:Forward Observer",
    "FOR:Forage", "FRG:Forgery", "FRM:Farming", "FSH:Fishing",
    "GEO:Geology", "GS:Gunsmith", "HW:Heavy Weapons", "IF:Indirect Fire",
    "INS:Instruction", "INT:Interrogation", "JP:Jet Pilot", "LB:Longbow",
    "LAP:Light Aircraft Pilot", "LCG:Large Caliber Gun", "LNG:Language",
    "LP:Lockpick", "MC:Melee Combat", "MCY:Motorcycle", "MEC:Mechanic",
    "MED:Medical", "MET:Meterology", "MNE:Mining Engineer",
    "MTL:Metallurgy", "MTN:Mountaineering", "NWH:Nuclear Warhead",
    "PAR:Parachute", "PST:Pistol", "RCN:Recon", "RWP:Rotary Wing Pilot",
    "SBH:Small Boat Handling","SCD:Scuba Diving", "SCR:Scrounging",
    "SWM:Swimming", "TW:Thrown Weapon", "TVD:Tracked Vehicle Driver",
    "WVD:Wheeled Vehicle Driver"]

我只想将此列表输出为简单的 2 列格式以减少空间。理想情况下,列之间应该有标准数量的空间,但我可以使用它。

ACM:Aircraft Mechanic        BC:Body Combat 
BIO:Biology         CBE:Combat Engineer 
CHM:Chemistry       CMP:Computers
CRM:Combat Rifeman      CVE:Civil Engineer 
DIS:Disguise            ELC:Electronics 
EQ:Equestrian           FO:Forward Observer
FOR:Forage          FRG:Forgery 
FRM:Farming             FSH:Fishing
GEO:Geology             GS:Gunsmith 
HW:Heavy Weapons        IF:Indirect Fire
INS:Instruction             INT:Interrogation 
JP:Jet Pilot            LB:Longbow
 LAP:Light Aircraft Pilot       LCG:Large Caliber Gun 
LNG:Language            LP:Lockpick 
MC:Melee Combat         MCY:Motorcycle 
MEC:Mechanic            MED:Medical 
MET:Meterology      MNE:Mining Engineer
MTL:Metallurgy      MTN:Mountaineering 
NWH:Nuclear Warhead     PAR:Parachute 
PST:Pistol          RCN:Recon 
RWP:Rotary Wing Pilot       SBH:Small Boat Handling 
SCD:Scuba Diving        SCR:Scrounging
SWM:Swimming        TW:Thrown Weapon 
TVD:Tracked Vehicle Driver  WVD:Wheeled Vehicle Driver

【问题讨论】:

  • 能否提供实际输入值和预期输出格式?您的输入列表是什么样的还不是很清楚。

标签: python string formatting


【解决方案1】:

由制表符分隔的两列连接成行。在 itertools 中查找迭代器等效项,以实现节省空间的解决方案。

import string
def fmtpairs(mylist):
    pairs = zip(mylist[::2],mylist[1::2])
    return '\n'.join('\t'.join(i) for i in pairs)

print fmtpairs(list(string.ascii_uppercase))

A   B
C   D
E   F
G   H
I   J
...

糟糕...被 S.Lott 抓住了(谢谢)。

一种更通用的解决方案,可以处理任意数量的列和奇数列表。对S.lott 稍作修改,使用生成器来节省空间。

def fmtcols(mylist, cols):
    lines = ("\t".join(mylist[i:i+cols]) for i in xrange(0,len(mylist),cols))
    return '\n'.join(lines)

【讨论】:

  • 第二部分太棒了!
【解决方案2】:

这行得通

it = iter(skills_defs)
for i in it:
    print('{:<60}{}'.format(i, next(it, "")))

见: String format examples

【讨论】:

    【解决方案3】:

    篇幅较长,我将其分为两部分。

    def columns( skills_defs, cols=2 ):
        pairs = [ "\t".join(skills_defs[i:i+cols]) for i in range(0,len(skills_defs),cols) ]
        return "\n".join( pairs )
    

    显然,它可以作为一个单独的 loooong 语句来完成。

    这也适用于奇数个技能。

    【讨论】:

      【解决方案4】:

      这是 gimel 提供的解决方案的扩展,它允许打印等间距的列。

      def fmtcols(mylist, cols):
          maxwidth = max(map(lambda x: len(x), mylist))
          justifyList = map(lambda x: x.ljust(maxwidth), mylist)
          lines = (' '.join(justifyList[i:i+cols]) 
                   for i in xrange(0,len(justifyList),cols))
          print "\n".join(lines)
      

      返回类似这样的东西

      ACM:Aircraft Mechanic BC:Body Combat
      BIO:Biology CBE:Combat Engineer
      CHM:Chemistry CMP:Computers
      CRM:Combat Rifeman CVE:Civil Engineer
      DIS:Disguise ELC:Electronics ... ...`

      【讨论】:

      • 在我的字符串列表中尝试您的方法时出现此错误:
        Traceback (most recent call last): File "tars.py", line 45, in &lt;module&gt; print fmtcols(jobs,3) File "tars.py", line 10, in fmtcols maxwidth = max(map(lambda x: len(x), mylist)) File "tars.py", line 10, in &lt;lambda&gt; maxwidth = max(map(lambda x: len(x), mylist)) TypeError: object of type 'int' has no len()
      【解决方案5】:
      data = [ ("1","2"),("3","4") ]
      print "\n".join(map("\t".join,data))
      

      不如 ActiveState 解决方案灵活,但更短:-)

      【讨论】:

      • 这并不能解决问题,只是插入制表符会导致列在内容宽度不同时脱节(如 OP 的“坏”输出示例)
      • @sidewinderguy 但它很短 :-)
      • 确实很短:)
      【解决方案6】:

      format_columns 函数应该做你想做的事:

      from __future__ import generators
      try: import itertools
      except ImportError: mymap, myzip= map, zip
      else: mymap, myzip= itertools.imap, itertools.izip
      
      def format_columns(string_list, columns, separator=" "):
          "Produce equal-width columns from string_list"
          sublists= []
      
          # empty_str based on item 0 of string_list
          try:
              empty_str= type(string_list[0])()
          except IndexError: # string_list is empty
              return
      
          # create a sublist for every column
          for column in xrange(columns):
                  sublists.append(string_list[column::columns])
      
          # find maximum length of a column
          max_sublist_len= max(mymap(len, sublists))
      
          # make all columns same length
          for sublist in sublists:
               if len(sublist) < max_sublist_len:
                   sublist.append(empty_str)
      
          # calculate a format string for the output lines
          format_str= separator.join(
              "%%-%ds" % max(mymap(len, sublist))
               for sublist in sublists)
      
          for line_items in myzip(*sublists):
              yield format_str % line_items
      
      if __name__ == "__main__":
          skills_defs = ["ACM:Aircraft Mechanic", "BC:Body Combat", "BIO:Biology",
              "CBE:Combat Engineer", "CHM:Chemistry", "CMP:Computers",
              "CRM:Combat Rifeman", "CVE:Civil Engineer", "DIS:Disguise",
              "ELC:Electronics","EQ:Equestrian", "FO:Forward Observer",
              "FOR:Forage", "FRG:Forgery", "FRM:Farming", "FSH:Fishing",
              "GEO:Geology", "GS:Gunsmith", "HW:Heavy Weapons", "IF:Indirect Fire",
              "INS:Instruction", "INT:Interrogation", "JP:Jet Pilot", "LB:Longbow",
              "LAP:Light Aircraft Pilot", "LCG:Large Caliber Gun", "LNG:Language",
              "LP:Lockpick", "MC:Melee Combat", "MCY:Motorcycle", "MEC:Mechanic",
              "MED:Medical", "MET:Meterology", "MNE:Mining Engineer",
              "MTL:Metallurgy", "MTN:Mountaineering", "NWH:Nuclear Warhead",
              "PAR:Parachute", "PST:Pistol", "RCN:Recon", "RWP:Rotary Wing Pilot",
              "SBH:Small Boat Handling","SCD:Scuba Diving", "SCR:Scrounging",
              "SWM:Swimming", "TW:Thrown Weapon", "TVD:Tracked Vehicle Driver",
              "WVD:Wheeled Vehicle Driver"]
      
          for line in format_columns(skills_defs, 2):
              print line
      

      这假设您有一个带有可用生成器的 Python。

      【讨论】:

        【解决方案7】:

        我认为其中许多解决方案都将两个不同的东西合二为一。

        你想:

        1. 能够强制字符串为特定宽度
        2. 打印表格

        这里有一个非常简单的方法:

        import sys
        
        skills_defs = ["ACM:Aircraft Mechanic", "BC:Body Combat", "BIO:Biology",
        "CBE:Combat Engineer", "CHM:Chemistry", "CMP:Computers",
        "CRM:Combat Rifeman", "CVE:Civil Engineer", "DIS:Disguise",
        "ELC:Electronics","EQ:Equestrian", "FO:Forward Observer",
        "FOR:Forage", "FRG:Forgery", "FRM:Farming", "FSH:Fishing",
        "GEO:Geology", "GS:Gunsmith", "HW:Heavy Weapons", "IF:Indirect Fire",
        "INS:Instruction", "INT:Interrogation", "JP:Jet Pilot", "LB:Longbow",
        "LAP:Light Aircraft Pilot", "LCG:Large Caliber Gun", "LNG:Language",
        "LP:Lockpick", "MC:Melee Combat", "MCY:Motorcycle", "MEC:Mechanic",
        "MED:Medical", "MET:Meterology", "MNE:Mining Engineer",
        "MTL:Metallurgy", "MTN:Mountaineering", "NWH:Nuclear Warhead",
        "PAR:Parachute", "PST:Pistol", "RCN:Recon", "RWP:Rotary Wing Pilot",
        "SBH:Small Boat Handling","SCD:Scuba Diving", "SCR:Scrounging",
        "SWM:Swimming", "TW:Thrown Weapon", "TVD:Tracked Vehicle Driver",
        "WVD:Wheeled Vehicle Driver"]
        
        # The only thing "colform" does is return a modified version of "txt" that is
        # ensured to be exactly "width" characters long. It truncates or adds spaces
        # on the end as needed.
        def colform(txt, width):
            if len(txt) > width:
                txt = txt[:width]
            elif len(txt) < width:
                txt = txt + (" " * (width - len(txt)))
            return txt
        
        # Now that you have colform you can use it to print out columns any way you wish.
        # Here's one brain-dead way to print in two columns:
        for i in xrange(len(skills_defs)):
            sys.stdout.write(colform(skills_defs[i], 30))
            if i % 2 == 1:
                sys.stdout.write('\n')
        

        【讨论】:

          【解决方案8】:

          这也可能对您有所帮助。

          for i in skills_defs:
          if skills_defs.index(i)%2 ==0:
              print(i.ljust(30),end = " ")
          else:
              print(i.ljust(30))
          

          【讨论】:

            猜你喜欢
            • 2021-03-25
            • 2016-12-15
            • 1970-01-01
            • 2020-11-24
            • 1970-01-01
            • 1970-01-01
            • 2012-02-12
            • 2016-12-26
            • 1970-01-01
            相关资源
            最近更新 更多