为什么我的代码无法获得预期的回报?
grade=['Ben Anderson',95,90,100,-1,'Mary Johnson',75,78,79,-5,'Michael Walter',80,68,0]
def convert_grades(lst):
a = []
b = []
for i in lst:
if isinstance(i,str):
c = 0
while lst[c] < 0 or lst[c] == []:
a = a + lst[c]
c = c + 1
b = b + a
return b
我希望它回来作为为什么我的代码无法获得预期的回报?
[['Ben Anderson',95,90,100],['Mary Johnson',75,78,79],['Michael Walter',80,68,0]]
但作为回报[]
我不知道发生了什么事情做。需要帮助。
尝试这样:
grade=['Ben Anderson',95,90,100,-1,'Mary Johnson',75,78,79,-5,'Michael Walter',80,68,0]
def convert_grades(lst):
a = []
for i in lst:
if isinstance(i,str):
a.append([]) #if a string is found than append a [] to a
a[-1].append(i) #append i to the last element of a
elif i>=0:
a[-1].append(i) #if not string then just append i to the last element of a
return a
print(convert_grades(grade))
输出:
[['Ben Anderson', 95, 90, 100], ['Mary Johnson', 75, 78, 79], ['Michael Walter', 80, 68, 0]]
你应该解释为什么他的原始代码是错误的:(有一个明显的问题,通过向他展示他的打印品 – User007 2012-08-14 22:04:00
'lst [0] heltonbiker 2012-08-14 22:24:31
我想itertools.groupby()
可能是非常适用的位置:
from itertools import groupby
def convert_grades(lst):
key = lambda x: isinstance(x, int) and x < 0
return [list(g) for k, g in groupby(lst, key) if not k]
结果:
>>> convert_grades(['Ben Anderson',95,90,100,-1,'Mary Johnson',75,78,79,-5,'Michael Walter',80,68,0])
[['Ben Anderson', 95, 90, 100], ['Mary Johnson', 75, 78, 79], ['Michael Walter', 80, 68, 0]]
这是通过创建一个函数key
返回True
当列表条目应该作为分隔作用,并False
当它不应该。通过在itertools.groupby()
中使用此函数,我们可以创建所有组,然后我们只需要筛选出所得到的迭代器中的所有分隔符值。
输入和输出的相同形式的建议:原代码的非pythonicity的
def convert_grades(lst):
out = []
for element in grade:
if isinstance(element, str):
buf = [] # re-initializes 'buf' everytime there is a string
out.append(buf)
buf.append(element)
return out
三大主要症状:
- 算术运算符的用途,其中有人已经熟悉Python的成语将使用类型方法(在这种情况下为
list.append
); - 在列表中输入明显的数据类型应该是字典的输入(尽管控制数据的方式并不总是可能的);
- 而且,最严重的症状是,OUTPUT是实际请求字典时的列表列表。
所以,另一个更Python的方式,返回一个字典而不是列表:
def convert_grades(lst):
out = {}
for element in grade:
if isinstance(element, str):
key = element
out[key] = []
else:
out[key].append(element) ## mind that this would raise an error if first element in lst is not string
return out
print convert_grades(grade)
希望这有助于!
另一个答案(虽然我喜欢比我更F.J's answer)和少数意见(只是建议):
#!/usr/bin/env python
def convert_grades1(lst):
a = []
b = []
index = 0
while index < len(lst):
if isinstance(lst[index], str):
b.append(lst[index])
index = index + 1
try:
while isinstance(lst[index], int):
if lst[index] > 0:
b.append(lst[index])
index += 1
except IndexError:
print "We're done"
finally:
a.append(b)
b = []
return a
if __name__ == "__main__":
grade=['Ben Anderson',95,90,100,-1,'Mary Johnson',75,78,79,-5,'Michael Walter',80,68,0]
print convert_grades1(grade)
1)
如果你 “行走” 的清单(或文件解析或任何...)与而循环认为如果你真的需要重新开始从一个嵌套循环开始走。在您的代码:
for i in lst:
if isinstance(i,str):
c = 0
while lst[c] < 0 or lst[c] == []:
你开始重新走在一段时间(你做c=0
就在它变得之前),即使你可能已经处理它在以前块为“全名单通行证”。我猜你在考虑i
是索引(不是,i
获取列表中的项目的值)。为索引,可使用:for i in range(0, len(lst))
或for i, item in enumerate(lst)
2)
c = 0
while lst[c] < 0 or lst[c] == []:
在那里,lst[c]
指向列表中的(拳头项含义中,串'Ben Anderson'
),这是既不小于0也不是空列表,所以while
循环永远不会被执行。
3)
它通常被认为是“Python化”具有以下的“更好比安全对不起”,所以不是if isinstance(i,str)
你可以(在你的例子)尝试解析一个int,如果知道你的代码它失败了......那么你可以认为它是一个字符串。
if isinstance(element, str):
#do stuff for string
else:
#do other stuff (for int)
可等效(你的情况):
try:
int(element)
#do other stuff (for int)
except ValueError:
#do stuff for string
要小心,因为int("5")
不会引发任何异常(即使"5"
实际上是一个str
)。它会给你一个int
的值为5
。
4)
如果你是一个初学者,print
是你的朋友;)
只要是完整的,你可以把这个结构[str, int, int, str, int]
作为栈和左起流行结构,你希望:
grades=['Ben Anderson',95,90,100,-1,'Mary Johnson',75,78,79,-5,'Michael Walter',80,68,0]
converted_list=[]
while grades:
temp=[grades.pop(0)]
while grades and isinstance(grades[0],int):
temp.append(grades.pop(0))
converted_list.append(temp)
print converted_list
打印:
[['Ben Anderson', 95, 90, 100, -1], ['Mary Johnson', 75, 78, 79, -5], ['Michael Walter', 80, 68, 0]]
您可以使用相同的方法来创建词典,这似乎是一个更好的数据结构:
d={}
while grades:
name=grades.pop(0)
d[name]=[]
while grades and isinstance(grades[0],int):
d[name].append(grades.pop(0))
print d
打印:
{'Mary Johnson': [75, 78, 79, -5], 'Michael Walter': [80, 68, 0], 'Ben Anderson': [95, 90, 100, -1]}
虽然这个作品,恕我直言,F.J的答案是最 'Python化'
如果你想有一个理解,这个工程:
grades=['Ben Anderson',95,90,100,-1,'Mary Johnson',75,78,79,-5,'Michael Walter',80,68,0]
eyes=[i for i, x in enumerate(grades)
if isinstance(x,str)]+[len(grades)+1] # index of the strings
LofSL=[(i,j) for i,j in zip(eyes[:-1],eyes[1:])] # slices for each list
LoL=[grades[t[0]:t[1]] for t in LofSL] # your list of lists
或者,如果你想要一本字典:
DofL={grades[t[0]]:grades[t[0]+1:t[1]] for t in LofSL}
建议:帮你调试,用'到处print'来看看怎么回事。如果它是'[]'主要是你的一些逻辑没有解决。这是调试问题的最简单方法。 – User007 2012-08-14 22:00:26
我会说,虽然从未执行......不知道,但 – BorrajaX 2012-08-14 22:04:06
@BorrajaX是的。因为第一个元素是“Ben Anderson”,并且它是一个字符串。第二个条件是'lst [0]'必须是一个空列表,而不是。所以它总是返回虚假:) – User007 2012-08-14 22:05:23