【问题标题】:How to join list in Python but make the last separator different?如何在 Python 中加入列表但使最后一个分隔符不同?
【发布时间】:2015-07-17 00:22:28
【问题描述】:

如果只有两个项目,或者在最后两个项目之间使用逗号和 & 符号,我正在尝试将列表转换为用 & 符号连接的分隔字符串,例如

Jones & Ben
Jim, Jack & James

我目前有这个:

pa = ' & '.join(listauthors[search])

并且不知道如何解决逗号/与号问题。初学者,所以一个完整的解释将不胜感激。

【问题讨论】:

    标签: python


    【解决方案1】:
    "&".join([",".join(my_list[:-1]),my_list[-1]])
    

    我认为可行

    或者只是

    ",".join(my_list[:-1]) +"&"+my_list[-1]
    

    处理只能处理 2 个项目的极端情况

    "&".join([",".join(my_list[:-1]),my_list[-1]] if len(my_list) > 2 else my_list)
    

    【讨论】:

    • 一百万次我需要这个。我希望有一个内置的字符串方法,或者 join() 将被更新以接受最后一个连接的可选第二个参数。
    【解决方案2】:

    你可以把它分成两个连接。使用", " 加入除最后一项之外的所有项目。然后用" & "连接这个字符串和最后一项。

    all_but_last = ', '.join(authors[:-1])
    last = authors[-1]
    
    ' & '.join([all_but_last, last])
    

    注意:这不处理边缘情况,例如authors 为空或只有一个元素时。

    【讨论】:

      【解决方案3】:

      一个班轮。只需使用, 作为分隔符连接除最后一个元素之外的所有元素。然后只需将& 附加到最后一个元素。

      print ', '.join(lst[:-1]) + ' & ' + lst[-1]
      

      如果您希望处理空列表等:

      if len(lst) > 1:
          print ', '.join(lst[:-1]) + ' & ' + lst[-1]
      elif len(lst) == 1:
          print lst[0]
      

      【讨论】:

        【解决方案4】:
        ('{}, '*(len(authors)-2) + '{} & '*(len(authors)>1) + '{}').format(*authors)
        

        此解决方案可以处理长度 > 0 的作者列表,但也可以对其进行修改以处理长度为 0 的列表。这个想法是首先创建一个格式字符串,我们可以通过解包列表来格式化。此解决方案避免了对列表进行切片,因此对于大型作者列表应该相当有效。

        首先,我们将'{}, ' 连接到两位作者之外的每一位作者。然后如果有两个或更多作者,我们连接'{} & '。最后我们为最后一个作者附加'{}',但是如果我们希望能够处理一个空的作者列表,这个子表达式可以是'{}'*(len(authors)>0)。最后,我们通过使用*解包语法解包列表的元素来格式化我们完成的字符串。

        如果你不需要单行,这里是高效函数形式的代码。

        def format_authors(authors):
            n = len(authors)
            if n > 1:
                return ('{}, '*(n-2) + '{} & {}').format(*authors)
            elif n > 0:
                return authors[0]
            else:
                return ''
        

        这可以处理任意长度的作者列表。

        【讨论】:

        • 我喜欢!我没想过只用一个格式化字符串来尝试它。不知道我会知道从哪里开始。
        • @DougR。那么这个想法就是坐下来想想数学公式。如果作者的长度大于 1,我们只需要 & 符号。我们只希望每个大于 2 的作者使用 1 个逗号分隔符。这很优雅,因为 'anystring'*0 只是空字符串。
        • 我还有一个问题。是否可以调整此方法以在与号之前插入逗号以获取长度为 n 的列表,其中 n > 2?即,“吉姆、杰克、 和约翰。”这不是作为“问题”提出的,而是作为一个真正的问题,因为大多数美国风格的手册都要求这样做。坦率地说,如果不将if n > 1: ... 转换为if n > 2: ... / elif n > 1: ...,我没有办法做到这一点,而对于这样一个优雅的解决方案,这似乎是错误的。谢谢!
        • @DougR。 Tbh,if n > 2: ... elif n > 1 解决方案没有任何问题。它相当优雅。事实上,这正是我会做的。就像if n > 2: return ('{}, '*(n-2) + '{}, & {}').format(*authors) elif: n > 1: return '{} & {}'.format(*authors) elif etc.... 一样简单,但是如果你真的想避免出于任何原因添加另一个 if 块,你可以在最后一部分使用'{}' + ','*(n>2) + ' & {}'。在我看来,这实际上是 less 优雅的,但它可以工作,因为布尔值被隐式转换为 1 和 0。 :)
        • 要使用牛津逗号(& 之前最后一个单词后的逗号,您可以扩展格式字符串的逻辑。('{}, '*(len(authors)-2) + '{} and '*(len(authors)==2) + '{}, and '*(len(authors)>2) + '{}').format(*authors) 牛津通用的挑战在于,如果列表仅长度为 2,您不希望在“And”之前使用逗号。函数解决方案是微不足道的,因为它只是另一个条件,所以我把它省略了。
        【解决方案5】:

        您可以简单地使用 Indexng 和 F-strings (Python-3.6+):

        In [1]: l=['Jim','Dave','James','Laura','Kasra']                                                                                                                                                            
        
        In [3]: ', '.join(l[:-1]) + f' & {l[-1]}'                                                                                                                                                                      
        
        Out[3]: 'Jim, Dave, James, Laura & Kasra'
        

        【讨论】:

          【解决方案6】:

          看起来,当我正在研究我的答案时,可能有人用类似的答案打败了我。这是我的比较。请注意,这也处理列表中 0、1 或 2 个成员的情况。

          # Python 3.x, should also work with Python 2.x.
          def my_join(my_list):
              x = len(my_list)
              if x > 2:
                  s = ', & '.join([', '.join(my_list[:-1]), my_list[-1]])
              elif x == 2:
                  s = ' & '.join(my_list)
              elif x == 1:
                  s = my_list[0]
              else:
                  s = ''
              return s
          
          assert my_join(['Jim', 'Jack', 'John']) == 'Jim, Jack, & John'
          assert my_join(['Jim', 'Jack']) == 'Jim & Jack'
          assert my_join(['Jim',]) == 'Jim'
          assert my_join([]) == ''
          

          【讨论】:

            【解决方案7】:

            只是一个语法更正确的例子:)

            def list_of_items_to_grammatical_text(items):
                if len(items) <= 1:
                    return ''.join(items)
                if len(items) == 2:
                    return ' and '.join(items)
                return '{}, and {}'.format(', '.join(items[:-1]), items[-1])
            

            输出示例:

            l1 = []
            l2 = ["one"]
            l3 = ["one", "two"]
            l4 = ["one", "two", "three"]
            
            list_of_items_to_grammatical_text(l1)
            Out: ''
            
            list_of_items_to_grammatical_text(l2)
            Out: 'one'
            
            list_of_items_to_grammatical_text(l3)
            Out: 'one and two'
            
            list_of_items_to_grammatical_text(l4)
            Out: 'one, two, and three'
            

            【讨论】:

              【解决方案8】:

              这是一个简单的,也适用于空或 1 元素列表:

              ' and '.join([', '.join(mylist[:-1])]+mylist[-1:])
              

              它起作用的原因是对于空列表,[:-1] 和 [-1:] 再次给我们一个空列表

              【讨论】:

                【解决方案9】:

                这是一个处理所有边缘情况(空列表、一个条目、两个条目)的单行示例:

                ' & '.join(filter(None, [', '.join(my_list[:-1])] + my_list[-1:]))
                

                filter() 函数用于过滤掉my_list 为空或只有一个条目时发生的空条目。

                【讨论】:

                  猜你喜欢
                  • 2013-01-31
                  • 1970-01-01
                  • 2018-05-25
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-08-22
                  • 2013-02-07
                  • 2018-02-22
                  相关资源
                  最近更新 更多