【问题标题】:Join author names with first ones separated by comma and last one by "and"加入作者姓名,第一个用逗号分隔,最后一个用“and”
【发布时间】:2013-04-04 14:11:24
【问题描述】:

我对 Python 完全陌生,并且有一个由\and 分隔的名称列表,我需要将第一个用逗号分隔,最后一个用“and”分隔。但是,如果名称超过 4 个,则返回值应该是第一个名称以及短语“et al.”。所以如果我有

 authors = 'John Bar \and Tom Foo \and Sam Foobar \and Ron Barfoo'

我应该得到“John Bar et al.”。而与

authors = 'John Bar \and Tom Foo \and Sam Foobar'

我应该得到“John Bar, Tom Foo and Sam Foobar”。

它还应该只使用一个作者姓名,并单独返回该单一姓名(和姓氏)。

我尝试做类似的事情

  names = authors.split('\and')
  result = ', '.join(names[:-1]) + ' and '.join(names[-1])

但这显然行不通。所以我的问题是如何使用joinsplit 让第一作者用逗号分隔,最后一个作者用“and”分隔,考虑到如果作者超过四位,则只应返回第一作者姓名与“等人”。

【问题讨论】:

  • 你有什么问题?
  • 你确定'\and'?应该是r'\and''\\and'
  • 您应该详细说明您是如何尝试解决问题的(代码、基本算法),这样可以集中帮助而不是为您完成工作。
  • authors.split(' \and ') 是一个很好的起点

标签: python join


【解决方案1】:

从拆分名称开始:

names = [name.strip() for name in authors.split(r'\and')]  # assuming a raw \ here, not the escape code \a.

然后根据长度重新加入:

if len(names) >= 4:
    authors = '{} et al.'.format(names[0])
elif len(names) > 1:
    authors = '{} and {}'.format(', '.join(names[:-1]), names[-1])
else:
    authors = names[0]

这也适用于只有一个作者的条目;我们只是将名称重新分配给authors

组合成一个函数:

def reformat_authors(authors):
    names = [name.strip() for name in authors.split(r'\and')]
    if len(names) >= 4:
        return '{} et al.'.format(names[0])
    if len(names) > 1:
        return '{} and {}'.format(', '.join(names[:-1]), names[-1])
    return names[0]

带有演示:

>>> reformat_authors(r'John Bar \and Tom Foo \and Sam Foobar \and Ron Barfoo')
'John Bar et al.'
>>> reformat_authors(r'John Bar \and Tom Foo \and Sam Foobar')
'John Bar, Tom Foo and Sam Foobar'
>>> reformat_authors(r'John Bar \and Tom Foo')
'John Bar and Tom Foo'
>>> reformat_authors(r'John Bar')
'John Bar'

【讨论】:

  • 对于只有一位作者的条目,这将返回 ` 和 John Bar`。 edit 哦,你刚刚修好了;没关系:-)
  • 很好,尽管使用join() 来处理固定大小为 2 的列表有点过头了,你不觉得吗?
  • @TimPietzcker:这是我认为更好的 filter(bool, ..) 方法的延续。
  • @MartijnPieters 感谢您的帮助。但是我不明白为什么我得到的反对票与答案一样多。即使在我编辑了我的问题之后,我也得到了新的反对票。
  • 我猜人们是这样投票的,因为您自己没有表现出任何研究成果。您基本上要求人们为您编写代码。不过我只能猜测动机。
【解决方案2】:

让我们把这个问题分成几部分:

首先,获取单个作者的列表:

>>> authors = 'John Bar \\and Tom Foo \\and Sam Foobar \\and Ron Barfoo'
>>> authorlist = [item.strip() for item in authors.split("\\and")]
>>> authorlist
['John Bar', 'Tom Foo', 'Sam Foobar', 'Ron Barfoo']

现在检查列表中的条目数量并采取相应措施:

>>> if len(authorlist) > 3:
...     print("{0} et al.".format(authorlist[0]))
... elif len(authorlist) == 1:
...     print(authorlist[0])
... else:
...     print("{0} and {1}".format(", ".join(authorlist[:-1]), authorlist[-1]))
...
John Bar et al.

【讨论】:

  • @PiotrHajduga:哎呀!感谢您发现这一点。
【解决方案3】:
def natural_join(val, cnj="and"):
    if isinstance(val, list):
        return " ".join((", ".join(val[0:-1]), "%s %s" % (cnj, val[-1]))) if len(val) > 1 else val[0]
    else:
        return val

natural_join(['pierre'])
# 'pierre'

natural_join(['pierre', 'paul'])
# 'pierre and paul'

natural_join(['pierre', 'paul', 'jacques'])
# 'pierre, paul and jacques'

natural_join(['pierre', 'paul', 'jacques'], cnj="et")
# 'pierre, paul et jacques'

【讨论】:

    【解决方案4】:

    看来您应该查看string.split 方法。这里有几个案例:要么有一个名字,要么有 2-3 个名字,要么有 4 个以上的名字。这些中的每一个都需要单独处理,因此只需弄清楚每种情况下需要做什么:

    # First split up the names by your specified delimiter (and strip off whitespace)
    names = [name.strip() for name in authors.split(r'\and')]
    
    # Now deal with your three cases for formatting.
    if len(names) == 1:
        print names[0]
    elif len(names) < 4:
        print ', '.join(names[:-1])+' and '+names[-1]
    else:
        print names[0]+' et al.'
    

    【讨论】:

      【解决方案5】:

      首先,您应该拆分您的字符串,以使用 split 获取名称。

      parts = author.split(' \and ')
      

      然后你应用你的条件:

      1. 如果有4个或更多的名字,返回第一个名字+'el at'

        if len(parts) >= 4:
            return parts[0]+' et al'
        
      2. 如果有超过 1 个名字,用 ', ' 连接它们,最后一个用 ' 和 ' 连接

        elif len(parts) > 1:
            return ' and '.join([', '.join(parts[:-1]), parts[-1]])
        
      3. 如果只有一个名字,返回那个名字。

        return parts[0] 
        

      最终功能:

      def my_func(author):
          parts = author.split(' \and ')
          if len(parts) >= 4:
              return parts[0]+' et al'
          elif len(parts) > 1:
              return ' and '.join([', '.join(parts[:-1]), parts[-1]])
          return parts[0] 
      

      【讨论】:

      • 结果中缺少 and
      • 一开始我和cmd有同样的反对意见,但是现在你的解决方案在只有一个作者的情况下返回' and John Bar'
      猜你喜欢
      • 2012-12-16
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 2017-01-04
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2012-07-06
      相关资源
      最近更新 更多