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

前者のコードの非pythonicityの3つの主な症状:

  1. list.appendPythonのイディオムに既に精通している人が型メソッド(この場合)を使用する算術演算子の使用。
  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)

お役に立てれば!

于 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返す関数を作成することで機能します。この関数を使用することで、すべてのグループを作成できます。その後、結果の iterable からすべての区切り値を除外するだけで済みます。TrueFalseitertools.groupby()

于 2012-08-14T22:11:20.667 に答える
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 に答える
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入る直前に実行します) 。あなたはインデックスになることを考えていたと思います(そうではなく、リスト内のアイテムの値を取得します)。インデックスの場合は、次を使用します:またはiifor 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

完成させるために、この構造[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 に答える
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 に答える