用逗号和“and”将单词连接在一起

27
我正在学习 'Python自动化办公教程'。我无法弄清如何从下面的程序中删除最终输出逗号。目标是不断提示用户输入值,然后将其打印在列表中,并在结尾处插入“和”。输出应该类似于这样:
apples, bananas, tofu, and cats

我的看起来像这样:
apples, bananas, tofu, and cats,

那个最后的逗号让我疯了。
def lister():
    listed = []
    while True:
        print('type what you want to be listed or type nothing to exit')
        inputted = input()
        if inputted == '':
            break
        else:
            listed.append(inputted+',')
    listed.insert(-1, 'and')
    for i in listed:
        print(i, end=' ')
lister()

1
这个回答解决了你的问题吗?如何在Python中连接列表,但使最后一个分隔符不同? - Georgy
9个回答

46

你可以通过将格式化延迟到打印时来避免向列表中的每个字符串添加逗号。在 ', ' 上连接除最后一项以外的所有项目,然后使用格式化插入连接的字符串和最后一项通过 and 连接的项目:

listed.append(inputed)
...
print('{}, and {}'.format(', '.join(listed[:-1]), listed[-1]))

演示:

>>> listed = ['a', 'b', 'c', 'd']
>>> print('{}, and {}'.format(', '.join(listed[:-1]), listed[-1]))
a, b, c, and d

5
改善建议:str.format 不再推荐使用,而且从 3.6 版本开始添加了一种新的内联格式语法来进行格式化,这种方法使代码更易读。如果你想使用这种格式化方法,请使用以下语法: f"{', '.join(listed[:-1])}, and {listed[-1]}"。然而,我认为最易读的方式是不使用任何格式化:', '.join(listed[:-1]) + ", and" + listed[-1] - gntskn
1
@gntskn str.format 真的“不再推荐”吗?我认为格式化字符串本身更容易阅读,可以提取到一个 fmt 变量中等等。我相信在将本地变量粘贴到格式化字符串中时,使用 f"..." 字符串有其用途,但是完全说 str.format 不再推荐似乎有点过头了。 - Zac Crites
@ZacCrites 你说得对,我想的是“%”运算符。这就是我在午夜前用手机发帖的后果:p - gntskn
1
@gntskn 还要注意,在 Python 版本 < 3.6 中不支持 f-strings - Moses Koledoye
1
这段代码无法处理少于3个项目的列表。 - user3064538

20

接受的回答不错,但将此功能移入一个接受列表并处理列表中0、1或2个元素的独立函数可能会更好:

def oxfordcomma(listed):
    if len(listed) == 0:
        return ''
    if len(listed) == 1:
        return listed[0]
    if len(listed) == 2:
        return listed[0] + ' and ' + listed[1]
    return ', '.join(listed[:-1]) + ', and ' + listed[-1]

测试用例:

>>> oxfordcomma([])
''
>>> oxfordcomma(['apples'])
'apples'
>>> oxfordcomma(['apples', 'pears'])
'apples and pears'
>>> oxfordcomma(['apples', 'pears', 'grapes'])
'apples, pears, and grapes'

1
良好的模块化。对于一般情况,我认为更喜欢将列表传递给 join,并在最后一个项目前添加“and ”,以便逗号由 join 与其余项目一起添加:“', '.join(listed [:-1] + [f'and {listed [-1]}'])”...但这似乎只是一个简单的美学选择。 - Mark Reed

8
这将从最后一个单词中删除逗号。
listed[-1] = listed[-1][:-1]

这段代码的作用是取出列表中的最后一个值,使用=将这个值赋给listed[-1][:-1]。其中listed[-1]表示列表中的最后一个单词,[:-1]表示这个单词去掉最后一个字符的部分。

具体实现如下:

def lister():
    listed = []
    while True:
        print('type what you want to be listed or type nothing to exit')
        inputted = input()
        if inputted == '':
            break
        else:
            listed.append(inputted+',')
    listed.insert(-1, 'and')
    listed[-1] = listed[-1][:-1]
    for i in listed:
        print(i, end=' ')
lister()

这个很好用,谢谢你的回答。但是我不明白 (listed[-1] = listed[-1][:-1]) 这句话的意思。 - Admin_Who
@Admin_Who 我为您的答案添加了一份解释。 - Will Da Silva

4

稍微修改一下您的代码...

def lister():
    listed = []
    while True:
        print('type what you want to be listed or type nothing to exit')
        inputted = input()
        if inputted == '':
            break
        else:
            listed.append(inputted) # removed the comma here

    print(', '.join(listed[:-2]) + ' and ' + listed[-1])  #using the join operator, and appending and xxx at the end
lister()

你需要更多:OP已经在单个字符串中插入了逗号。 - Prune
这将在“and”后面添加一个逗号。 - Jonas Schäfer

3
listed[-1] = listed[-1][:-1]

这将截断listed中最终字符串的最后一个字符。


3
我会使用f-string(Python 3.6+中提供的格式化字符串字面量)来完成它:
def grammatically_join(words, oxford_comma=False):
    if len(words) == 0:
        return ""
    if len(words) == 1:
        return listed[0]
    if len(words) == 2:
        return f"{listed[0]} and {listed[1]}"
    return f'{", ".join(words[:-1])}{"," if oxford_comma else ""} and {words[-1]}'

如果您不需要使用牛津逗号(Oxford comma),那么您可以简化代码并删除len(words) == 2的额外边缘情况:
def grammatically_join(words):
    if len(words) == 0:
        return ""
    if len(words) == 1:
        return listed[0]
    return f'{", ".join(words[:-1])} and {words[-1]}'

2
有很多方法可以做到,但这个怎么样?
# listed[-1] is the last element of the list
# rstrip removes matching characters from the end of the string
listed[-1] = listed[-1].rstrip(',')
listed.insert(-1, 'and')
for i in listed:
    print(i, end=' ')

您仍然会在行尾打印一个空格,但我猜您看不到它,因此也不会在意。 :-)


0

假设您在只有两个项目时可以接受逗号,这是相当紧凑的:

def commaize(items):
    return ', and'.join(', '.join(items).rsplit(',', 1))

它的行为类似于这样:

>>> commaize([])
''
>>> commaize(['apples'])
'apples'
>>> commaize(['apples', 'bananas'])
'apples, and bananas'
>>> commaize(['apples', 'bananas', 'tofu', 'cats'])
'apples, bananas, tofu, and cats'

0

我通过使用 inflect 包和 p.join() 解决了这个问题。

import inflect
p = inflect.engine()
nameList = []
while True:
    try:
        names = input("Name: ")
        nameList.append(names)

    except EOFError:
        break


lastStr = p.join(nameList , ",")
print("\r", lastStr)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接