110 likes | 300 Views
Sequences and Indexing. A sequence is a type of thing that represents a: Finite, ordered collection of things Indexed by non-negative integers . For example: A list : [ 'red' , 'white' , 'blue' ] A string : 'Check out Joan Osborne, super musician'
E N D
Sequencesand Indexing • A sequenceis a type of thing that represents a: • Finite, ordered collectionof things • Indexed by non-negative integers. • For example: • A list: ['red', 'white', 'blue'] • A string: 'Check out Joan Osborne, super musician' • A tuple: (800, 400, 310) • You can still get to the items(aka elements) in the collection, by indexing: • colors =['red', 'white', 'blue'] • colors[0]has value 'red' • colors[1]has value 'white' • colors[2]has value 'blue' Indexing starts at zero, not at one The len function returns the length of the sequence, that is, the number of items in the sequence.
Patterns for Looping (“iterating”) through the items of sequences Beginning To End Basic idea: You want to iterate through ALL of a sequence, from its beginning to its end. In this example, the code iterates through the entire FORWARDs looking at EVERY ITEM, printing those items. forkinrange(len(sequence)): ... sequence[k] ... fork in range(len(sequence)): print(sequence[k]) Be sure that you understand the use of the index k in the above example. It is not a “magic” symbol; it is just an ordinary variable that goes 0, 1, 2, ... per the range statement. Do you see now why the range statement is defined to start at 0 and ends one short of the value of its argument?
Patterns for Looping (“iterating”) through the items of sequences Other Ranges Basic idea: You want to iterate through PART of a sequence, or perhaps through it backwards, or some combination of both. Form 1 Form 3 Form 2 forkinrange(NUMBER): ... sequence[BLAH] ... forkinrange(BLAH): ... sequence[k] ... m= ... forkinrange(NUMBER): ... sequence[m] ... where NUMBERis the number of items in the sequence to examine and BLAHis some formula involving k that is carefully crafted to produce exactly the right indices. where BLAH is some range OTHER than 0, 1, 2, ... that is carefully crafted to produce exactly the right indices. where NUMBER is the number of items in the sequence to examine and mis an auxiliary variable that is carefully controlled to produce exactly the right indices. Examples for each form. In each example, the code iterates through the code BACKWARDS looking at EVERY 3rd ITEM, printing those items. last = len(sequence) – 1 fork in range(len(sequence) // 3): print(sequence[last - (k * 3)]) last = len(sequence) - 1 fork in range(last, -1, -3): print(sequence[k]) last = len(sequence) – 1 m = last fork in range(len(sequence) // 3): print(sequence[m]) m = m - 3
Patterns for Looping (“iterating”) through the items of sequences Selecting Items Basic idea: You examine all or some of the items in the sequence, but use an IF statement to process only ones that satisfy a certain condition. In this example, the code selects the items that are integers (and counts them, returning the count). forkinrange(len(sequence)): if ...sequence[k] ...: ... sequence[k] ... defcount_integers(sequence): count = 0 for k in range(len(sequence)): if type(sequence[k]) == int: count = count + 1 return count I have shown the pattern combined with the Beginning-To-End pattern, but it could also be used with any of the Other-Ranges patterns.
Patterns for Looping (“iterating”) through the items of sequences Finding something Basic idea: You examine all or some of the items in the sequence, looking for one that satisfies a certain condition. When you find such an item, you return its index (position) in the sequence. If there is no item in the sequence that meets the condition, you return -1. forkinrange(len(sequence)): if ...sequence[k] ...: returnk return-1 In this example, the code returns the index of the first item it finds that is bigger than 20. deffind_bigger_than_20(sequence): forkin range(len(sequence)): ifsequence[k] > 20: return k return-1 I have shown the pattern combined with the Beginning-To-End pattern, but it could also be used with any of the Other-Ranges patterns. In a variation of this pattern, the function might return True if it found an item that meets the condition, or False if not. Or, in another variation, it might return the item that is found, or None if there is no item in the sequence that meets the condition. Note the placement of the second return statement. This is NOT the time for an if-else in the loop!
Patterns for Looping (“iterating”) through the items of sequences Two places at once Basic idea: At each iteration of the loop, you examine TWO items in the sequence during that iteration. forkinrange(BLAH): ... sequence[INDEX_1] ... sequence[INDEX_2] ... In this example, the code compares each item to the NEXT item in the sequence, counting the number of times that the next one is bigger than the current one, and returns that count. For example, if the sequence is [9, 7, 12, 35, 24, 25], the function returns 3 because 12 is bigger than 7,35 is bigger than 12, and 25 is bigger than 24. • where: • BLAHis some range appropriate to the problem, • INDEX_1 is some function of k that gives ONE of the “two places at once” to examine, and • INDEX_2 is another function of k that gives the OTHER of the “two places at once” to examine. • Typically, INDEX_1 or INDEX_2 (but not both!) is simply k. defcount_increases(sequence): count = 0 forkinrange(len(sequence) - 1): ifsequence[k + 1] > sequence[k]: count = count + 1 returncount You often have to restrict the range to less than the entire sequence when using this pattern, as in the example to the right.
Patterns for Looping (“iterating”) through the items of sequences Parallel sequences Basic idea: At each iteration of the loop, you examine TWO SEQUENCES, looking at the kth item of each, during that iteration. forkinrange(len(sequence1)): ... sequence1[k] ... sequence2[k] ... In this example, the code compares each item in one sequence to its “parallel” item in the other sequence, counting the number of times that the latter is bigger than the former, and returns that count. For example, if the sequences are: [11, 22, 10, 44, 33, 12] [55, 10, 30, 29, 31, 30] then this function returns 3,since 55 > 11 and 30 > 10 and 30 > 12. The above assumes that the two sequences are the same length, but variations can remove that restriction. defcount_bigger(sequence1, sequence2): count = 0 forkinrange(len(sequence1)): ifsequence2[k] > sequence1[k]: count = count + 1 returncount Using parallel sequences is an error-prone approach, since it is easy to modify one sequence and forget to modify the “parallel” sequence. Nonetheless, this is an important pattern to understand.
Patterns for Looping (“iterating”) through the items of sequences Max or Min Basic idea: You examine all or some of the items in the sequence, looking for the biggest (or smallest) one. Return the index of that item (or perhaps just the item itself). k_for_max= 0 forkinrange(1, len(sequence)): if sequence[k] > sequence[k_for_max]: k_for_max = k return k_for_max In this example, the code returns the index of the smallest item in the sequence. defindex_of_min(sequence): k_for_min = 0 forkinrange(1, len(sequence)): ifsequence[k] < sequence[k_for_min]: k_for_min= k returnk_for_min The above is for Max. Reverse the comparison in the IF statement for Min. In a variation of this pattern, the function might return sequence[k_for_max] instead of k_for_max. I have shown the pattern combined with the Beginning-To-End pattern, but it could also be used with any of the Other-Ranges patterns. Do you see why the range starts at 1, not at 0? This pattern requires that the sequence be non-empty.