输入:['apples','bananas','tofu','cats']
输出:苹果,香蕉,豆腐和猫
此当然应该为任何列表工作。所以我想出了以下代码:
def listToString(someList):
for i in range(len(someList)):
newString = str(someList[i])
if i == (len(someList)-1):
print('and ' + str(someList[i]))
else:
print(newString, end=', ')
someList = ['apples','bananas','tofu','cats']
listToString(someList)
我觉得我并没有使用本章中讲授的所有内容(例如某些方法)解决问题。有没有更有效的方法来编码该项目?
#1 楼
您可能已经使用了多种方法来进行列表切片。我不知道您是否已经在书中学习过
.join()
和.format()
方法,但我会使用。<注释:
函数和变量应为
snake_case
而不是CamelCase
列表字符串应返回字符串而不是打印它,因为这就是名字的含义。
def list_to_string(a_list):
return '{0} and {1}'.format(', '.join(a_list[:-1]), a_list[-1])
some_list = ['apples','bananas','tofu','cats']
print(list_to_string(some_list))
它是如何工作的?
.format()
替换为{0}
,', '.join(a_list[:-1])
加入列表,直到最后一项[:-1]
以及逗号和空格。将{1}
替换为列表a_list[-1]
中的最后一项。评论
\ $ \ begingroup \ $
感谢您的提示,我真的需要习惯命名约定。我确实知道.format()函数! .join()我不知道。基本上,.join()函数从列表中获取元素并将其连接,直到给定索引? btw的format()函数非常聪明,这对我而言是没有发生的!谢谢你的时间!
\ $ \ endgroup \ $
–sar91
17-10-7在14:17
\ $ \ begingroup \ $
但是,这有三个缺点:1.仅适用于字符串列表2.对于长度为1的列表,例如[“ foo”],它返回“和foo”(OP的代码有相同的问题) 3.空列表将引发IndexError。
\ $ \ endgroup \ $
–地狱
17-10-7在15:24
\ $ \ begingroup \ $
值得一提的是,现代Python已格式化了字符串文字(即f'{','。join(a_list [:-1])}和{a_list [-1]}')
\ $ \ endgroup \ $
– gntskn
17-10-7在22:59
\ $ \ begingroup \ $
轻微的nitpick:{0}后需要一个逗号,因为该示例包括牛津逗号。
\ $ \ endgroup \ $
–user87373
17年10月8日在9:57
\ $ \ begingroup \ $
@gntskn您不是指f“ {','。join(a_list [:-1])}和{a_list [-1]}”吗?
\ $ \ endgroup \ $
– wizzwizz4
17-10-8在19:26
#2 楼
Ludisposed的答案已经有了很大的改进,但是它没有考虑一些特殊情况:它仅适用于字符串列表。
对于长度为1的列表,例如
["foo"]
,它返回" and foo"
(您的代码有相同的问题)。它在一个空列表上引发
IndexError
。此代码避免了以下问题:
def list_to_string(a_list):
if not a_list:
return ""
elif len(a_list) == 1:
return str(a_list[0])
else:
body = ", ".join(map(str, a_list[:-1]))
return '{0} and {1}'.format(body, a_list[-1])
当前没有牛津逗号,如您的代码。但是您可以轻松地将其添加为另一种特殊情况(不要在
len(a_list) == 2
时添加,否则请添加)。感谢@DavidK在评论中指出了这一点。评论
\ $ \ begingroup \ $
感谢您的深刻见解!您的第二点是绝对正确的,我没有只使用列表中的一个元素来测试我的代码。除了两件事,我了解了您的大多数代码:(i)第一个if语句,对于检查的内容我有些困惑? 'if not a_list'-是否检查a_list是否为空? (ii).join()函数中的“ map”语句。我现在将对其进行谷歌搜索,但是对此有任何见解将不胜感激!非常感谢您的宝贵时间。
\ $ \ endgroup \ $
–sar91
17-10-7在19:22
\ $ \ begingroup \ $
在python中,空列表被认为是Falsey。 map(str,list)将整个列表转换为字符串。
\ $ \ endgroup \ $
–处置不良
17-10-7在19:31
\ $ \ begingroup \ $
是的,如果检查以下陈述的真实性。一个空列表是虚假的,一个非空列表是虚假的,并且当然不会将其反转。 map接受一个函数(此处为str)并将其应用于可迭代对象的每个元素(如列表)。它返回Python中的地图对象,该对象可以再次迭代。在Python 2中,它只是返回了一个列表
\ $ \ endgroup \ $
–地狱
17-10-7在19:32
\ $ \ begingroup \ $
@ sar91大多数Python对象都是这种情况。空列表,字符串,元组,集合,字典...都是假的。通常,任何具有len(obj)== 0的对象都是假的(除非可以不同地指定它)。
\ $ \ endgroup \ $
–地狱
17-10-8在8:48
\ $ \ begingroup \ $
在问题和此处的所有答案(到目前为止)中,存在牛津逗号的用法问题,该逗号出现在3个或更多项目的列表中(缺少几个答案,包括此内容),但不在2个项目的列表中(但由OP和另一个答案插入)。我喜欢这个答案的原因是它很容易扩展,以区分2的列表和3的列表,并在每种情况下适当地处理逗号。
\ $ \ endgroup \ $
– David K
17-10-8在19:55
#3 楼
基本问题考虑到您正在学习,我想评论一下我所看到的函数的基本问题,而不仅仅是编写代码的简洁性。
没有返回值
编程的很大一部分是使函数模块化,而我们通常通过将任务分解成可重复的部分来实现。像您一样使用打印语句将打印到控制台,甚至可能对您当前的问题有意义,但是当您想在其他地方使用它时会发生什么呢?如果要将奇特的字符串保存到磁盘上怎么办?
答案是像其他答案一样返回字符串。然后,有了字符串后,就可以执行所需的操作,例如将其打印或写入磁盘。
应该养成从函数中返回值的习惯。
名称误导
函数名称暗示它从列表中返回一个字符串。想象一下,您从现在开始四个月后返回代码,并尝试使用此函数写入文件,您将被证明编写这样的文件:
fancy_string = list_to_string(groceries)
with open('groceries.txt', 'w') as groceries_file:
groceries_file.write(fancy_string)
但是,这将不起作用,因为这里没有返回值。
在编程中,命名是一件非常困难的事情,因此请仔细考虑您的名字。 br />
现在我想指出的是一些更小的事情,以使代码更具pythonic的含义。
for i in range(len(someList)):
newString = str(someList[i])
可以替换为:
for i, newString in enumerate(someList):
现在也用newString替换someList [i]的实例:
def listToString(someList):
for i, newString in enumerate(someList):
if i == (len(someList)-1):
print('and ' + str(newString))
else:
print(newString, end=', ')
即使在这种情况下,您应该在其他帖子的开头使用更多答案,但对于需要枚举的情况,最好了解枚举与列表的元素。我鼓励您使用Python for-loop构造,而不必尽可能索引所有内容。
PEP 8
正如其他人指出的那样,该代码不符合Python标准PEP8。
虽然我不知道严格遵循PEP 8的代码,但您应该看看它是什么样子。
评论
\ $ \ begingroup \ $
enumerate()函数非常酷。我一定会记住这一点。还要感谢您提供所有其他很棒的技巧,非常感谢!关于使函数模块化的非常好一点-使返回值的必要性非常明显!
\ $ \ endgroup \ $
–sar91
17年10月8日在7:12
#4 楼
其他一些答案给出了很好的指导,但是代码示例引入了一些我不建议使用的可读性问题。将此示例与其他示例进行比较:
def list_to_string(list_object):
# corner case 1: not a list object
if not isinstance(list_object, list):
raise ValueError('function parameter is not a list')
# corner case 2: list object has 0 element
if not list_object:
raise ValueError('list is empty aka evaluated as false')
# corner case 3: list object has 1 element
if len(list_object)==1:
return str(list_object[0])
# actual use case
else:
# convert list elements to string
str_list = [str(x) for x in list_object]
bulk, last = str_list[:-1], str_list[-1]
bulk_str = ', '.join(bulk)
new_string = bulk_str + ' and ' + last
return new_string
评论
\ $ \ begingroup \ $
我可能会补充说f字符串或.format()比字符串串联更干净。其次,对于@Grapiher处理的int列表,此操作失败
\ $ \ endgroup \ $
–处置不良
17-10-9在15:22
\ $ \ begingroup \ $
另外,您也可以一次性返回else中的字符串,而不是先将其分配给变量。像return f'{body}和{last}'
\ $ \ endgroup \ $
–处置不良
17-10-9在15:27
\ $ \ begingroup \ $
添加了用于处理更多极端情况的代码。这不是最简洁的代码,但我相信应该强调清晰度。
\ $ \ endgroup \ $
– BCR
17-10-9在15:48
#5 楼
您可以简单地将这个问题分为两部分,其中第一部分将在开始和开始之前打印列表项,然后打印列表的最后两项(包括列表)。spam = ['apples', 'bananas', 'tofu', 'cats', 'mewoeto']
def andInsertedList(spamList):
for i in range(len(spamList)-1):
print(spamList[i], end=', ') #First Part
print('and ' + spamList[len(spamList)-1]) #Second Part
andInsertedList(spam)
评论
\ $ \ begingroup \ $
最后一行:“ spamList [len(spamList)-1]”不需要计算最后一项“ len(spamList)-1”的索引值即可检索它。您可以简单地使用“ spamList [-1]”
\ $ \ endgroup \ $
– DataWriter
19年5月17日在18:16
评论
没有理由在Python中使用range(len(_))。只是遍历集合本身。如果还需要索引,请使用enumerate。由于短名单的所有特殊情况,这实际上是一个棘手的练习。 (它似乎希望以标准的书面英语输出,但在这种情况下,“和”仅适用于2个或更多项目的列表,而牛津逗号应仅出现在3个或更多项目的列表中。介绍性练习,除非重点是如何处理复杂的规范。)