object - Python TypeError in traversing a list -
i'm teaching myself python 3.2 , i'm trying make program match list of names. plist multidimensional list string @ column 0, integer @ column 1, , boolean @ column 2. however, whenever try , call function (which runs if number of rows in list even), typeerror.
traceback (most recent call last): file "c:\users\metc\dropbox\assassins.py", line 150, in <module> main() file "c:\users\metc\dropbox\assassins.py", line 11, in main update(ops, plist) file "c:\users\metc\dropbox\assassins.py", line 125, in update b = match(plist) file "c:\users\metc\dropbox\assassins.py", line 47, in match q, p = 0 typeerror: 'int' object not iterable any appreciated, keep in mind i'm beginner language, gentle. :) don't mind if technical though; have experience computer science.
def match(plist): b = [] z = len(plist)-1 x in range(z): b.append([plist[x][0],0]) x in range(z): isvalid = false q, p = 0 while isvalid == false: q = random.randint(0, z) print('q ' + str(q)) if q > z: isvalid = false elif q < 0: isvalid = false elif plist[q][1] == true: isvalid = false else: isvalid = true ismatch = false while ismatch == false: if plist[q][1] == false: isvalid = false while isvalid == false: p = random.randint(0,z) print('p ' + str(p)) if p > z: isvalid = false elif p < 0: isvalid = false elif plist[p][2] == true: isvalid = false else: if q == p: isvalid = false else: isvalid = true print('match valid') b[q][1] = plist[p][0] ismatch = true print('') return b
you've made logic far, far complicated, point i'm going have make several passes down size , show you're doing wrong.
first, we'll fix actual reported error, others noted. @ same time, we'll apply simple principle: don't compare boolean literals. don't "if true raining, need umbrella". "if raining, need umbrella". cut out stuff. if isvalid more clear if isvalid == true, highlights isvalid supposed mean. i'm going take out debug traces (print statements there check if code's doing right thing; simplify code first, , there less check).
def match(plist): b = [] z = len(plist)-1 x in range(z): b.append([plist[x][0],0]) x in range(z): isvalid = false q = p = 0 while not isvalid: q = random.randint(0, z) if q > z: isvalid = false elif q < 0: isvalid = false elif plist[q][1]: isvalid = false else: isvalid = true ismatch = false while not ismatch: if not plist[q][1]: isvalid = false while not isvalid: p = random.randint(0,z) if p > z: isvalid = false elif p < 0: isvalid = false elif plist[p][2]: isvalid = false else: if q == p: isvalid = false else: isvalid = true b[q][1] = plist[p][0] ismatch = true return b next, we're going simplify our conditional logic. first off, result returned random.randint(0, z) cannot < 0 nor > z, ever, no matter what. that's part of point of function. there no point in writing code handle cases , in fact wrong so. writing code handle implies happen. that's distraction person reading code, , lie, @ that. puts space between things matter (the call random.randint , check against plist value).
we're going simplify if/else pairs set boolean accordingly. same reason wouldn't write
if x == 1: y == 1 elif x == 2: y == 2 # ... etc. ad infinitum every possible integer value of x you shouldn't same booleans, either. finally, can , should use logical and , or connect boolean conditions.
def match(plist): b = [] z = len(plist)-1 x in range(z): b.append([plist[x][0],0]) x in range(z): isvalid = false q = p = 0 while not isvalid: q = random.randint(0, z) isvalid = not plist[q][1] ismatch = false while not ismatch: if not plist[q][1]: isvalid = false while not isvalid: p = random.randint(0,z) isvalid = not plist[p][2] , (q != p) b[q][1] = plist[p][0] ismatch = true return b my next step fix list indexing. indexing lists usually not want, , here in fact introduces bug. it's evident want iterate on each "row" of plist; range(z) gives numbers 0 z-1 inclusive, it's incorrect subtract 1 len(plist) in calculating z. example, if plist has 5 elements, calculate z = 4, , produce range(z) = [0, 1, 2, 3]. never access plist[4], , b have 4 elements.
you doing 2 things z, fundamentally. 1 make loop run many times there "rows" in plist, , (in first loop) each "row".
this important: range not magic, , has no special connection for-loops. it's function produces list of numbers. in python, for loop gives elements directly. indexing nonsense - nonsense, best left less capable languages. if want each element of list, do each element of list, writing code loops on each element of list. directly. not on separate list of indices use index original. that's going out of way make things complicated.
the second thing z generate random number that's possible index, can index plist random row. in other words, want choose random row. just choose random row. random module provides functionality directly: function called random.choice, , sounds like.
there's 1 small hitch here: original code compares p == q, i.e. compares 2 randomly chosen list indices equality. if we're no longer indexing, don't have indices compare. fix this, need understand original purpose was: check whether new chosen row old chosen row again. again, simplify checking directly: pick new row instead of new index, , see if is old one.
we have problem need choose corresponding row b corresponds whichever row in plist have identified q. deal that, can select b row @ same time plist row. little tricky: approach make list of pairs of rows - in each pair, there row b , row plist. doesn't require complicated - there in fact built-in function stitch b , plist want: it's called zip. anyway, having chosen row-pair list of row-pairs, have unpack 2 rows 2 variables - using q, p = ... syntax mistakenly using in first place, turns out. that's it's for.
with these changes, can rid of p, q , z entirely. nice, because it's not @ clear names supposed mean anyway.
def match(plist): b = [] row in plist: b.append([row[0], 0]) row in plist: isvalid = false while not isvalid: first_row, b_row = random.choice(zip(plist, b)) isvalid = not first_row[1] ismatch = false while not ismatch: if not first_row[1]: isvalid = false while not isvalid: second_row = random.choice(plist) isvalid = not second_row[2] , (first_row not second_row) b_row[1] = second_row[0] ismatch = true return b time little more logical cleanup. in first while loop, keep looping until isvalid becomes true. say, until not first_row[1] becomes true. in second while loop, first_row never gets changed, so, since not first_row[1] true when loop started, remain true entire time. therefore, if-check unnecessary.
once that's gone, find second while loop useless: loop while not ismatch, i.e. until ismatch. ismatch? well, before start loop, it's false, , @ end of loop, it's true. always. know code run once. enter loop, go end, set ismatch true, , exit, since ismatch, having been set true, true. code runs once doesn't need loop; it's code.
another thing i'll here clean while isvalid loops little bit converting them break out when we're done. break not evil (and neither continue). simplify our thinking booleans, because aren't checking against not isvalid more (emphasis on not); we're directly comparing have assigned isvalid. , means rid of isvalid variable, too, again name doesn't tell much.
def match(plist): b = [] row in plist: b.append([row[0], 0]) row in plist: while true: first_row, b_row = random.choice(zip(plist, b)) if not first_row[1]: break while true: second_row = random.choice(plist) if not second_row[2] , (first_row not second_row): break b_row[1] = second_row[0] return b one last thing: can construct b more cleanly. building list appending elements sucker's game. don't tell python how build lists. knows how. instead, ask list meets specifications, list comprehension. more shown explained (if need explanation, please consult google), i'll go ahead , give 1 more version:
def match(plist): b = [[row[0], 0] row in plist] row in plist: while true: first_row, b_row = random.choice(zip(plist, b)) if not first_row[1]: break while true: second_row = random.choice(plist) if not second_row[2] , (first_row not second_row): break b_row[1] = second_row[0] return b from here on, it's hard correct or improve without understanding what you're doing. after work, i still have no idea!
the way have set up, choose random row, many times there rows - still choose duplicates. want? or did want choose each row once in random order? what's significance of doing in random order, anyway?
after choosing first row, choose random second row match. did want 1 random row per first row? or did want try possible pairs of rows?
and of data, anyway? output b data represent? in plist begin with, , why called plist? "matching" match function? can't imagine.
Comments
Post a Comment