John Joseph said unto the world upon 08/01/06 06:36 AM: > --- Guillermo Fernandez Castellanos > <[EMAIL PROTECTED]> wrote: > > >>Hi, >> >>Look at this: >> >>> i=[1,2,3] >> >>> i[len(i)] >>Traceback (most recent call last): >> File "<stdin>", line 1, in ? >>IndexError: list index out of range >> >> >>This means that I have tried to access an element >>that is out of the >>list, in this case i[3], that is, the 4th element of >>the list. >> >>You are doing the same. You do a >>j in range(len(seats)) >>and then you are accessing your list with seats[j] >>and seats[j+1]. What >>happens when j = len(seats)-1 and you call >>seats[j+1]? :-) >> >>It happens indeed the same that in the example I >>gave you first. >> >>Hope it helps. Good luck, >> > > > Thanks for the advice > But I need to display the results > What should I do in the for loop for this message > to go > my for loop is as > > for j in range(length) : > if seats[j] <> seats[j+1]: > print " The Seat", j , "And the seat", > j+1 , "value, which are", seats[j]," and", seats[j+1], > "are not same" > else: > print "The Seats ",j ,"And the seats", > j+1, "Values,", seats[j], "and", seats[j+1], "are > same" > Thanks > Joseph John
Joseph, I think Guillermo has already given you the answer :-). But, I'll make it more explicit. I'll also do a rather more. My intent is to give you some idea of how you can go about incrementally improving your code. The code you posted is doing something like: >>> a_list = [7,8,7] >>> for index in range(len(a_list)): print index, a_list[index] print index + 1, len(a_list), a_list[index + 1] 0 7 1 3 8 1 8 2 3 7 2 7 3 3 Traceback (most recent call last): File "<pyshell#97>", line 3, in -toplevel- print index + 1, len(a_list), a_list[index + 1] IndexError: list index out of range Examine the output. When the iteration hits the last member of the list (when it gets to the final element of range(len(a_list)), there is no next element of the list, so the request to print the next element doesn't work. The list length is 3, so I get the same exception as if I'd done: >>> a_list[3] Traceback (most recent call last): File "<pyshell#16>", line 1, in -toplevel- a_list[3] IndexError: list index out of range directly. That suggests *not* asking for an iteration which uses up the list -- leave a next element and the code will work: >>> for index in range(len(a_list) - 1): # Note the difference print index, a_list[index] print index + 1, len(a_list), a_list[index + 1] 0 7 1 3 8 1 8 2 3 7 >>> Of course, as you pointed out in your OP, right now, even with this fix, you will only be testing for sequential duplicates. My test list a_list = [7,8,7] has dupes, but your approach won't find them. Warning: I'm going to go into a number of issues that you might not yet entirely understand. If I lose you, don't worry; just ask about it. Let's both fix the requirement that the duplicates be sequential and start putting the code into functions. Consider this: >>> def dupe_detector_1(sequence): for item in sequence: if sequence.count(item) > 1: print "%s is duplicated!" %item >>> dupe_detector_1(a_list) 7 is duplicated! 7 is duplicated! >>> OK, that might be better, as we can find non-sequential duplicates. But, there are two problems. 1) The duplication warning is duplicated :-) and 2) >>> a_tuple = (4,3,4) >>> dupe_detector_1(a_tuple) Traceback (most recent call last): File "<pyshell#47>", line 1, in -toplevel- dupe_detector_1(a_tuple) File "<pyshell#28>", line 3, in dupe_detector_1 if sequence.count(item) > 1: AttributeError: 'tuple' object has no attribute 'count' >>> The function signature seems to indicate it will work for all sequences, but it chokes on tuples. The second problem is easy to fix: >>> def dupe_detector_2(sequence): # coerce to a list as lists have count methods. sequence = list(sequence) for item in sequence: if sequence.count(item) > 1: print "%s is duplicated!" %item >>> dupe_detector_2((1,1,2)) 1 is duplicated! 1 is duplicated! >>> 1 down, 1 to go. >>> def dupe_detector_3(sequence): sequence = list(sequence) seen_dupes = [] for item in sequence: if item in seen_dupes: # if it is there, we already know it is duplicated continue elif sequence.count(item) > 1: print "%s is duplicated!" %item seen_dupes.append(item) >>> dupe_detector_3(a_list) 7 is duplicated! >>> That's much better :-) There remain 2 things I'd want to do differently. First, I'd separate the print logic from the detection logic: >>> def dupe_detector_4(sequence): '''returns a list of items in sequence that are duplicated''' sequence = list(sequence) seen_dupes = [] for item in sequence: if item in seen_dupes: # if it is there, we already know it is duplicated continue elif sequence.count(item) > 1: seen_dupes.append(item) return seen_dupes >>> big_list = [1,42,3,4,2,3,54,6,7,3,45,6,4,32,43,5,32,4,4,42,3,42,3] >>> dupes_in_big_list = dupe_detector_4(big_list) >>> dupes_in_big_list [42, 3, 4, 6, 32] OK, you might say "fine, but I *wanted* an on-screen report". Let's do that this way: >>> def print_dupe_report(sequence): '''prints a report of items in sequence that are duplicated''' dupes = dupe_detector_4(sequence) dupes.sort() for d in dupes: print "%s was duplicated" %d >>> print_dupe_report(big_list) 3 was duplicated 4 was duplicated 6 was duplicated 32 was duplicated 42 was duplicated >>> The advantage of this is you might well want to do what dupe_detector_4 does without the screen output. Making the function have a smaller job makes it easier to reuse in other contexts. The last thing is a bit subtle. Say I had a sequence of length 10**6 where most items were duplicated. dupe_detector_4 has to iterate over the entire long sequence, and continually hit the continue clause as it will have seen the item already. This last version will fix that, too: >>> def dupe_detector_5(sequence): '''returns a list of items in sequence that are duplicated''' sequence = list(sequence) seen_dupes = [] for item in set(sequence): # Note the difference if sequence.count(item) > 1: seen_dupes.append(item) return seen_dupes >>> dupes_in_big_list = dupe_detector_5(big_list) >>> dupes_in_big_list [32, 3, 4, 6, 42] >>> We no longer need the continue clause, as converting to set ensures we won't ever deal with the same item twice: >>> set((1,1,1,2,2,2,2,2,3,4,4,5)) set([1, 2, 3, 4, 5]) And, preventing us from dealing with the same item twice is what makes this better. To see that, consider: >>> def iteration_comparison(sequence): list_count = 0 set_count = 0 for i in list(sequence): list_count += 1 for i in set(sequence): set_count += 1 print list_count, set_count >>> iteration_comparison((1,2,3,4)) 4 4 >>> iteration_comparison((1,2,3,4,1,2,3,4,1,2,3,4,5,1,2,3,4,1,2,3,4)) 21 5 >>> For sequences with a lot of duplication, the set version (as in dupe_detector_5) has to iterate over far fewer items. That'll be quicker. OK, I hope most of that made sense. Best, Brian vdB _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor