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

但它返回为[]

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

4

6 回答 6

5

输入输出形式相同的建议:

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 性的三个主要症状:

  1. 在已经熟悉 python 习语的人会使用类型方法的情况下使用算术运算符(list.append在这种情况下);
  2. 列表中的输入,其中明显的数据类型应该是字典(尽管并不总是可以控制获取数据的方式);
  3. 而且,最严重的症状是,当它实际上是在乞求字典时,输出是一个列表列表。

因此,一种更 Pythonic 的方式,返回字典而不是列表:

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)

希望这可以帮助!

于 2012-08-14T22:19:59.137 回答
3

我认为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()我们可以创建所有的组,然后我们只需要从结果迭代中过滤掉所有的分隔符值。

于 2012-08-14T22:11:20.667 回答
1

为了完整起见,您可以将此结构[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]}

虽然这可行,但恕我直言,FJ的答案是最“Pythonic”

于 2012-08-14T23:41:02.797 回答
1

还有另一个答案(尽管我比我更喜欢FJ 的答案)和一些评论(只是建议):

#!/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)

如果您正在使用while循环“遍历”列表(或解析文件或其他...),请考虑您是否真的需要在嵌套循环中从头开始重新开始遍历。在您的代码中:

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]指向列表中的第一个项目(意思是 string 'Ben Anderson'),它既不小于 0 也不是空列表,因此while永远不会执行循环。

3)

它通常被认为是“pythonic”让你的代码遵循“更好的抱歉比安全”的想法,所以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是您的朋友;)

于 2012-08-14T22:36:55.087 回答
1

尝试这样的事情:

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]]
于 2012-08-14T22:01:45.713 回答
0

如果你想要理解,这有效:

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}
于 2012-08-15T01:06:09.247 回答