Parallel Arrays
Chapter 8
Two (or more) arrays are called parallel if their corresponding elements hold related information.
Try the following code from the video.
/*
* Example code with three 1D arrays that are parallel that contain:
* Names of specific people
* Ages of specific people
* Heights of specific people
* Because the arrays are parallel,
* for any index name[index], age[index], and height[index]
* are all describing the same person.
*/
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
// Find the largest value from an array
int maxValue(const int VALUES[], int length);
// Find the location of the largest value from an array
int maxIndex(const double VALUES[], int length);
// Lookup person's index by name. Return a negative number if not found.
int indexOfName(const string HAYSTACK[], const string& NEEDLE,
int length);
int main ()
{
const int PEOPLE_COUNT = 6;
// First names
string name[PEOPLE_COUNT] = {
"Michael", "Jessica", "Christopher", "Ashley", "Jairy", "Dondi"
};
// Age of each person in years old.
int age[PEOPLE_COUNT] = { 21, 17, 44, 45, 70, 65 };
// The height of each person in feet
double height[PEOPLE_COUNT] = { 6.7, 5.5, 6.6, 5.9, 6.5, 5.9 };
int personIndex;
string searchName;
// Display each persons information
cout << setw(12) << "Name" << setw(4) << "Age"
<< setw(7) << "Height" << endl;
for (int index = 0; index < PEOPLE_COUNT; ++index)
{
cout << setw(12) << name[index]
<< setw(4) << age[index]
<< setw(7) << height[index] << endl;
}
// Find the oldest person
cout << "The oldest person is " << maxValue(age, PEOPLE_COUNT)
<< " years old." << endl;
// Display information about the tallest person
personIndex = maxIndex(height, PEOPLE_COUNT);
cout << "The tallest person is named " << name[personIndex] << ".\n";
cout << name[personIndex] << " is " << age[personIndex]
<< " years old and "
<< height[personIndex] << "ft tall." << endl;
// Search for a person by name
cout << "Enter a name to look up: ";
cin >> searchName;
// Find the index of the person's name
personIndex = indexOfName(name, searchName, PEOPLE_COUNT);
if (personIndex >= 0 && personIndex < PEOPLE_COUNT)
{
cout << name[personIndex] << " is " << age[personIndex]
<< " years old." << endl;
}
else
{
cout << searchName << " is not in our database." << endl;
}
return 0;
}
int maxValue(const int VALUES[], int length)
{
// Initially, assert that the first value is the max.
auto max = VALUES[0];
// Check to see if any other value in the array is larger.
for (int index = 1; index < length; ++index)
{
// Update the max if the the value we are looking at is larger.
if (VALUES[index] > max)
max = VALUES[index];
}
return max;
}
int maxIndex(const double VALUES[], int length)
{
// Initially, assert that the first index is the location of the max.
int maxIndex = 0;
// Check to see if any other index has a larger vlue.
for (int index = 1; index < length; ++index)
{
// Update maxIndex f we the current location has a larger value.
if (VALUES[index] > VALUES[maxIndex])
maxIndex = index;
}
return maxIndex;
}
int indexOfName(const string HAYSTACK[], const string& NEEDLE,
int length)
{
// Check each location in the array for the search value.
for (int index = 0; index < length; ++index)
{
// If found, return it's location.
if (HAYSTACK[index] == NEEDLE)
{
return index;
}
}
// If we get here, the value was not found in the array.
// Return an invalid index (something negative).
return -1;
}The Problem: Multi-Type Data
Standard arrays can only hold elements of the same data type. If you need to store complex information about an object—such as a person's name (string), age (int), and height (double). A single basic array cannot do this.
Parallel arrays solve this by using separate arrays of different types that are "linked" by their index. For any index index, the values at name[index], age[index], and height[index] all describe the same person.
Organization and Declaration
To set up parallel arrays, define a shared constant for the size and declare each array:
constexpr int CLASS_SIZE = 50;
int studentId[CLASS_SIZE];
char courseGrade[CLASS_SIZE];Another example:
constexpr int COUNT = 6;
string name[COUNT] = { "Michael", "Jessica", "Ashley", ... };
int age[COUNT] = { 21, 17, 45, ... };
double height[COUNT] = { 6.7, 5.5, 5.9, ... };Processing with a Single Index
The primary advantage of parallel arrays is that a single index variable can iterate over and access all related data points simultaneously.
// Display a table of all related information
for (int index = 0; index < COUNT; ++index)
{
cout << setw(12) << name[index]
<< setw(4) << age[index]
<< setw(7) << height[index] << endl;
}The Power of Returning an Index
When working with parallel arrays, it is often better to write functions that return an index rather than a specific value.
- Value-based function:
double maxHeight(double height[], int size)returns6.7. You know the height, but you don't know who has that height. - Index-based function:
int tallestIndex(double height[], int size)returns0. With index0, you can look up the name (name[0]), age (age[0]), and height (height[0]).
TIP
Always prefer returning an index when the search result needs to be used across multiple parallel arrays.
Searching and Validation
When searching for a specific item (a "needle" in a "haystack"), your function should handle the case where the item is not found by returning an invalid index, typically -1.
int indexOfName(const string names[], string searchName, int size)
{
for (int index = 0; index < size; ++index)
{
if (names[index] == searchName)
{
return index;
}
}
return -1; // Not found
}Important: Boundary Guards
Always validate the returned index before using it. Accessing an array with a negative index or an index beyond its size can cause crashes, nonsensical output, or security vulnerabilities that could be exploited by hackers.
int personIndex = indexOfName(name, "Alice", COUNT);
if (personIndex >= 0 && personIndex < COUNT)
{
cout << name[personIndex] << " is " << age[personIndex] << " years old.";
}
else
{
cout << "Person not found in database.";
}