为什么我的代码无法获得预期的回报?

问题描述:

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]] 

但作为回报[]

我不知道发生了什么事情做。需要帮助。

+2

建议:帮你调试,用'到处print'来看看怎么回事。如果它是'[]'主要是你的一些逻辑没有解决。这是调试问题的最简单方法。 – User007 2012-08-14 22:00:26

+0

我会说,虽然从未执行......不知道,但 – BorrajaX 2012-08-14 22:04:06

+0

@BorrajaX是的。因为第一个元素是“Ben Anderson”,并且它是一个字符串。第二个条件是'lst [0]'必须是一个空列表,而不是。所以它总是返回虚假:) – User007 2012-08-14 22:05:23

尝试这样:

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]] 
+1

你应该解释为什么他的原始代码是错误的:(有一个明显的问题,通过向他展示他的打印品 – User007 2012-08-14 22:04:00

+0

'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()中使用此函数,我们可以创建所有组,然后我们只需要筛选出所得到的迭代器中的所有分隔符值。

+1

为什么downvote?我知道这并不完全回答“我的代码出了什么问题?”的问题,但提供一个替代解决方案可以帮助OP以不同的方式考虑问题。 – 2012-08-14 22:13:25

+2

downvotes *没有*解释没有建设性,也没有人帮忙 – Levon 2012-08-14 22:16:57

+2

这段代码对于初学者来说太复杂了,Lambda ....但是一个很好的代码 – User007 2012-08-14 22:20:04

输入和输出的相同形式的建议:原代码的非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 

三大主要症状:

  1. 算术运算符的用途,其中有人已经熟悉Python的成语将使用类型方法(在这种情况下为list.append);
  2. 在列表中输入明显的数据类型应该是字典的输入(尽管控制数据的方式并不总是可能的);
  3. 而且,最严重的症状是,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}