Data Structure Operations
This chapter covers two data structure operations: slicing and concatenation. Manipulation of these structures provides opportunities to create interesting musical changes.
Procedure
List Operations are a set of tools for modifying a list. We performed similar operations on strings in Chapter 13. Slice notation can be used to create a subset of a list from a larger, existing list. Its syntax is newList = oldList[startIndex: endIndex]
. As with string slices, the indices for slice notation are inclusive and exclusive, respectively.
Array Operations are a set of methods for modifying an array. We performed similar operations on strings in Chapter 13. Dot notation and the slice
method can be used to slice out an array from a larger, existing array. Its syntax is newArray = oldArray.slice(startIndex, endIndex)
. As with string slices, the indices are inclusive and exclusive, respectively.
Lists can also be combined with the concatenation operator (+
). The syntax is newList = listA + listB
.
Arrays can also be combined using the concat
method. The syntax is newArray = arrayA.concat(arrayB)
.
Let’s work through an example that uses concatenation and slicing. This example uses a new operator, modulo. The modulo operator (%
) returns the remainder of the division of two numbers instead of the quotient. For example, 7 % 3 = 1 and 8 % 3 = 2. This operator is useful for counting in cycles, like executing a block of code only every third measure.
The example below creates a beat that dynamically changes. Notice makeBeat()
's beat string contains numbers other than 0; it is accessing different indices of the drumSounds
list. Every four measures, the last element of drumSounds
is moved to the beginning of the list, so makeBeat()
's output changes. This is achieved by slicing two lists from drumSounds
, lastSound
and allButLastSound
. The last element of the drumSounds
list is sliced by using a starting index of len(drumSounds) - 1
and an ending index of len(drumSounds)
. The resulting lastSound
list is then concatenated to the front of the allButLastSound
list, to make a new version of drumSounds
. The if statement condition measure % 4 == 0
means this switch will only happen every 4 measures (when the value of measure
divided by 4 has no remainder).
The example below creates a beat that dynamically changes. Notice makeBeat()’s beat string contains numbers other than 0; it is accessing different indices of the `drumSounds
array. Every four measures, the last element of drumSounds
is moved to the beginning of the array, so makeBeat()’s output changes. This is achieved by slicing two arrays from `drumSounds
, lastSound
and allButLastSound
. The last element of the drumSounds
array is sliced by using a starting index of drumSounds.length - 1
and an ending index of drumSounds.length
. The lastSound
array is then concatenated to the front of the allButLastSound
array, to make a new version of drumSounds
. The if statement condition measure % 4 === 0
means this switch will only happen every 4 measures (when the value of measure
divided by 4 has no remainder).
# List Operations: Using list operations to change our drum sounds every four measures
# Setup
from earsketch import *
setTempo(120)
# Music
drumSounds = [OS_CLAP01, OS_CLOSEDHAT01, OS_COWBELL01, OS_KICK01, OS_LOWTOM01, OS_SNARE01]
beatString = "5-5132-034550011"
for measure in range(1, 33):
makeBeat(drumSounds, 1, measure, beatString)
if (measure % 4) == 0: # Only True at every fourth measure
# rotate list items so last item moves to first slot
listLength = len(drumSounds)
lastSound = drumSounds[listLength - 1 : listLength]
allButLastSound = drumSounds[0 : listLength - 1]
drumSounds = lastSound + allButLastSound
// Array operations: Using array operations to change our drum sounds every four measures
// Setup
setTempo(120);
// Music
var drumSounds = [OS_CLAP01, OS_CLOSEDHAT01, OS_COWBELL01, OS_KICK01, OS_LOWTOM01, OS_SNARE01];
var beatString = "5-5132-034550011";
for (var measure = 1; measure < 33; measure++) {
makeBeat(drumSounds, 1, measure, beatString);
if (measure % 4 == 0) { // Only true at every 4th measure
// rotate array items so last item moves to first slot
var arrLength = drumSounds.length;
var lastSound = drumSounds.slice(arrLength - 1, arrLength);
var allButLastSound = drumSounds.slice(0, arrLength - 1);
drumSounds = lastSound.concat(allButLastSound);
}
}
Chapter 19 Summary
-
Lists can be concatenated and sliced using list operations, a set of tools for modifying a list.
-
The syntax for creating a subset of a list from a larger, existing list is
newList = oldList[startIndex: endIndex]
. -
Lists can be combined using the concatenation operator,
+
, likenewList = listA + listB
. -
The modulo operator is used to obtain the remainder after dividing one number by another, rather than the quotient.
-
Arrays can be concatenated and sliced using array operations, a set of tools for modifying an array.
-
The syntax for slicing out an array from a larger, existing array is
newArray = oldArray.slice(startIndex: endIndex)
. -
Arrays can be combined using the
concat
method, likenewArray = arrayA.concat(arrayB)
. -
The modulo operator is used to obtain the remainder after dividing one number by another, rather than the quotient.
Questions
Which of the following operations is used to join lists/arrays?
-
Concatenation
-
Slicing
-
Modulo
-
Addition
Which of the following evaluates to True?
-
100 % 10 == 0
-
10 % 10 == 1
-
10 % 1 == 10
-
100 % 10 == 1