【问题标题】:Iterate a format string over a list在列表上迭代格式字符串
【发布时间】:2011-03-10 20:18:02
【问题描述】:

在 Lisp 中,你可以有这样的东西:

(setf my-stuff '(1 2 "Foo" 34 42 "Ni" 12 14 "Blue"))
(format t "~{~d ~r ~s~%~}" my-stuff)

迭代同一个列表的最 Pythonic 方式是什么?首先想到的是:

mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"]
for x in xrange(0, len(mystuff)-1, 3):
    print "%d %d %s" % tuple(mystuff[x:x+3])

但这对我来说感觉很尴尬。我确定有更好的方法吗?


好吧,除非有人后来提供了更好的例子,否则我认为 gnibbler 的解决方案是最好的\最接近的,尽管起初它的工作方式可能并不那么明显:

mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"]
for x in zip(*[iter(mystuff)]*3):
    print "{0} {1} {2}".format(*x)

【问题讨论】:

  • 顺便说一句,“尴尬”这个词是不是太棒了?它只是看起来尴尬!
  • 相比之下看起来很别扭,但确实没那么糟糕。
  • +1 因为我不知道您指的是我的评论还是代码。 不要澄清,模棱两可更有趣/有趣!

标签: python formatting iteration language-comparisons


【解决方案1】:
stuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"]

it = iter(stuff)
itn = it.next

print '\n'.join("%d %d %s" % (el,itn(),itn())
                for el in it)

我觉得很好理解

【讨论】:

    【解决方案2】:

    基于 Wright 的两个班轮:

    mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"]
    print '\n'.join("{0},{1},{2}".format(*mystuff[x:x+3]) for x in xrange(0, len(mystuff)-1, 3))
    

    【讨论】:

      【解决方案3】:

      我会说最 Pythonic 是让列表更深入:

      mystuff = [(1, 2, "Foo"), (34, 42, "Ni"), (12, 14, "Blue")]
      for triplet in mystuff:
          print "%d %d %s" % triplet
      

      【讨论】:

      • 这基本上就是 gnibblers 解决方案创建的内容:[x for x in zip(*[iter(mystuff)]*3)] = [(1, 2, 'foo'), (34, 42, 'ni'), (12, 14, 'blue')] 很漂亮,不是吗?
      • 我知道,但我认为以这种形式开始列表更符合 Pythonic。那是最初的问题,对吧?
      • 好吧,我有点模棱两可,所以我修正了措辞。我真的对迭代/格式化部分更感兴趣——每次迭代消耗一定数量的列表值。但就整个“程序”而言,您的解决方案会更加pythonic
      【解决方案4】:
      mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"]
      for x in zip(*[iter(mystuff)]*3):
          print "%d %d %s"%x
      

      或使用.format

      mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"]
      for x in zip(*[iter(mystuff)]*3):
          print "{0} {1} {2}".format(*x)
      

      如果格式字符串没有硬编码,您可以对其进行解析以计算出每行有多少项

      from string import Formatter
      num_terms = sum(1 for x in Formatter().parse("{0} {1} {2}"))
      

      把它们放在一起给出了

      mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"]
      fmt = "{0} {1} {2}"
      num_terms = sum(1 for x in Formatter().parse(fmt))
      for x in zip(*[iter(mystuff)]*num_terms):
          print fmt.format(*x)
      

      【讨论】:

      • 真的喜欢这个解决方案,一开始我真的很困惑,但是在破解了非常优雅的代码之后。
      【解决方案5】:

      我认为join是Python中最相似的特性:

      (format t "~{~D, ~}" foo)
      
      print(foo.join(", "))
      

      当你有多个项目时,情况会更糟,正如你所看到的,但如果你有一个group-by 函数(无论如何这真的很有用!),我认为你可以让它工作而不会有太多麻烦。比如:

      mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"]
      print(["%d %d %s" % x for x in group(mystuff, 3)].join("\n"))
      

      【讨论】:

      • 是的,加上一个专门的生成器函数,你可以让它看起来非常漂亮。
      • 是的,我想这取决于你想作弊的程度。如果某个周末你真的很无聊,你可以将FORMAT 移植到 Python 并说FORMAT(True, "~{~d ~r ~s~%~}", my_stuff)。 :-)
      • 我被诱惑了!当然,我也希望~r 也是 Python 库的一部分...... sourceforge 上已经有一个模块:sourceforge.net/projects/pynum2word
      【解决方案6】:

      对于初学者,我会使用 2.6+ 中较新的字符串格式化方法

      print "{0} {1} {2}".format(*mystuff[x:x+3])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-14
        • 1970-01-01
        • 2010-10-18
        • 2011-05-01
        • 2012-05-28
        • 1970-01-01
        相关资源
        最近更新 更多