# Perform operations on arrays using helper methods in C# ## Introduction Suppose you are a software developer on a team assigned to work with a logistics company. They have many needs for gathering and organizing their business data. Projects vary from tracking and reporting inventory, enabling specific data to be passed to and from business partners, and identifying possible fraudulent orders. Each project is different, but all require the processing of data. In these projects the applications will be performing data operations such as to add, delete, sort, combine, calculate, validate and format output. In this module, you'll use C# arrays to allow you to store sequences of values in a single data structure. Once you have data in an array, you can manipulate the order and the contents of the array. Furthermore, you'll be able to perform powerful string operations using array helper methods. With the use of several helper methods, you'll sort the data or reverse the order of the data. You'll clear out the items in the array and resize the array to add new items. You'll convert a string into an array by splitting it into smaller strings each time you encounter a character like a comma. You'll also split a string into an array of characters. Finally, you'll join all of the elements of an array into a single string. ### Learning objectives In this module you will: - Sort and reverse the order of array elements. - Clear and resize the elements of an array. - Split a `string` into an array of strings or characters (`chars`). - Join array elements into a `string`. ## Exercise - Discover Sort() and Reverse() The `Array` class contains methods that you can use to manipulate the content, arrangement, and size of an array. In this exercise, you'll write code that performs various operations on an array of pallet identifiers. Your code could be the start of an application to track and optimize the usage of pallets for the company. ### Create an array of pallets, then sort them Type the following code into the editor: ```cs string[] pallets = { "B14", "A11", "B12", "A13" }; Console.WriteLine("Sorted..."); Array.Sort(pallets); foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } ``` Take a minute to review the `Array.Sort(pallets);` line from the previous code you added. Here you're using the `Sort()` method of the `Array` class to sort the items in the array alphanumerically. The Program.cs file must be saved before building or running the code. At the Terminal command prompt, to run your code, type `dotnet run` and then press Enter. You should see the following output: ```txt Sorted... -- A11 -- A13 -- B12 -- B14 ``` ### Reverse the order of the pallets To reverse the order of the pallets using the `Array.Reverse()` method, update your code as follows: ```cs string[] pallets = { "B14", "A11", "B12", "A13" }; Console.WriteLine("Sorted..."); Array.Sort(pallets); foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } Console.WriteLine(""); Console.WriteLine("Reversed..."); Array.Reverse(pallets); foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } ``` Focus on the line of code `Array.Reverse(pallets);` line from the previous code you added. Here, you're using the `Reverse()` method of the `Array` class to reverse the order of items. Save your code file, and then run your code. You should see the following output: ```txt Sorted... -- A11 -- A13 -- B12 -- B14 Reversed... -- B14 -- B12 -- A13 -- A11 ``` ### Recap Here's a few important ideas that you covered in this unit: - The Array class has methods that can manipulate the size and contents of an array. - Use the `Sort()` method to manipulate the order based on the given data type of the array. - Use the `Reverse()` method to flip the order of the elements in the array. --- ## Exercise - Explore Clear() and Resize() As you continue building a pallet tracker for the logistics company, suppose you also need track new pallets and remove old pallets from tracking. How can you accomplish creating tracking functionality for adding and removing pallets? ### Use array methods to clear and resize an array The `Array.Clear()` method allows you to remove the contents of specific elements in your array and replace it with the array default value. For example, in a `string` array the element value cleared is replaced with `null`, when you clear a `int` array element the replacement is done with `0` (zero). The `Array.Resize()` method adds or removes elements from your array. Delete or use the line comment operator `//` to comment out all of the code from the previous exercises. Update your code in the editor as follows: ```cs string[] pallets = { "B14", "A11", "B12", "A13" }; Console.WriteLine(""); Array.Clear(pallets, 0, 2); Console.WriteLine($"Clearing 2 ... count: {pallets.Length}"); foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } ``` Take a minute to focus on the line of code `Array.Clear(pallets, 0, 2);`. Here you're using the `Array.Clear()` method to clear the values stored in the elements of the `pallets` array starting at index `0` and clearing `2` elements. The Program.cs file must be saved before building or running the code. At the Terminal command prompt, to run your code, type `dotnet run` and then press Enter. When you run the code, you'll see that the values stored in the first two elements of the array have been cleared out. In the Length property and the foreach statement, the elements still exist, but they're now empty. ```txt Clearing 2 ... count: 4 -- -- -- B12 -- A13 ``` ### Empty string versus null When you use `Array.Clear()`, the elements that were cleared no longer reference a string in memory. In fact, the element points to nothing at all. pointing to nothing is an important concept that can be difficult to grasp at first. What if you attempt to retrieve the value of an element that was affected by the `Array.Clear()` method, could you do it? #### Access the value of a cleared element Two approaches are needed to determine the value of a cleared element to see how the C# compiler works with a null value. Insert new code lines around the `Array.Clear(pallets, 0, 2);` code line as follows: ```cs Console.WriteLine($"Before: {pallets[0]}"); Array.Clear(pallets, 0, 2); Console.WriteLine($"After: {pallets[0]}"); ``` Verify your code should match the following code listing: ```cs string[] pallets = { "B14", "A11", "B12", "A13" }; Console.WriteLine(""); Console.WriteLine($"Before: {pallets[0]}"); Array.Clear(pallets, 0, 2); Console.WriteLine($"After: {pallets[0]}"); Console.WriteLine($"Clearing 2 ... count: {pallets.Length}"); foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } ``` Save your code file, and then run your code. You should see the following output: ```txt Before: B14 After: Clearing 2 ... count: 4 -- -- -- B12 -- A13 ``` If you focus on the line of output `After: `, you might think that the value stored in `pallets[0]` is an empty string. However, the C# Compiler implicitly converts the null value to an empty string for presentation. #### Call a string helper method on a cleared element To prove that the value stored in `pallets[0]` after being cleared is null, you 'll modify the code example to call the `ToLower()` method on `pallets[0]`. If it's a string, it should work fine. But if it's null, it should cause the code to throw an exception. To call the `ToLower()` method each time you attempt to write `pallets[0]` to the console, update your code as follows:: ```cs Console.WriteLine($"Before: {pallets[0].ToLower()}"); Array.Clear(pallets, 0, 2); Console.WriteLine($"After: {pallets[0].ToLower()}"); ``` Make sure your code matches the following code listing: ```cs string[] pallets = { "B14", "A11", "B12", "A13" }; Console.WriteLine(""); Console.WriteLine($"Before: {pallets[0].ToLower()}"); Array.Clear(pallets, 0, 2); Console.WriteLine($"After: {pallets[0].ToLower()}"); Console.WriteLine($"Clearing 2 ... count: {pallets.Length}"); foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } ``` Save your code file, and then run your code. This time, when you run the code, you'll see a large error message. If you parse through the text, you'll see the following message: ```txt System.NullReferenceException: Object reference not set to an instance of an object. ``` This exception is thrown because the attempt to call the method on the contents of the `pallets[0]` element happens before the C# Compiler has a chance to implicitly convert null to an empty string. The moral of the story is that `Array.Clear()` will remove an array element's reference to a value if one exists. To fix this, you might check for null before attempt to print the value. To avoid the error, add an if statement before accessing an array element that is potentially null. ```cs if (pallets[0] != null) Console.WriteLine($"After: {pallets[0].ToLower()}"); ``` #### Resize the array to add more elements Next, rework the code listing from Step 1 to include code to resize the array. When complete, your code should match the following code listing: ```cs string[] pallets = { "B14", "A11", "B12", "A13" }; Console.WriteLine(""); Array.Clear(pallets, 0, 2); Console.WriteLine($"Clearing 2 ... count: {pallets.Length}"); foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } Console.WriteLine(""); Array.Resize(ref pallets, 6); Console.WriteLine($"Resizing 6 ... count: {pallets.Length}"); pallets[4] = "C01"; pallets[5] = "C02"; foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } ``` Take a few minutes to focus on the line `Array.Resize(ref pallets, 6);`. Here, you're calling the `Resize()` method passing in the `pallets` array by reference, using the `ref` keyword. In some cases, methods require you pass arguments by value (the default) or by reference (using the ref keyword). The reasons why this is necessary requires a long and complicated explanation about of how objects are managed in .NET. Unfortunately, that is beyond the scope of this module. When in doubt, you're recommended to look at Intellisense or Microsoft Learn for examples on how to properly call a given method. In this case, you're resizing the `pallets` array from four elements to `6`. The new elements are added at the end of the current elements. The two new elements will be null until you assign a value to them. Save your code file, and then run your code. When you run the code, you should see the following output. ```txt Clearing 2 ... count: 4 -- -- -- B12 -- A13 Resizing 6 ... count: 6 -- -- -- B12 -- A13 -- C01 -- C02 ``` #### Resize the array to remove elements Conversely, you can remove array elements using `Array.Resize()`. Update your code in the editor as follows: ```cs string[] pallets = { "B14", "A11", "B12", "A13" }; Console.WriteLine(""); Array.Clear(pallets, 0, 2); Console.WriteLine($"Clearing 2 ... count: {pallets.Length}"); foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } Console.WriteLine(""); Array.Resize(ref pallets, 6); Console.WriteLine($"Resizing 6 ... count: {pallets.Length}"); pallets[4] = "C01"; pallets[5] = "C02"; foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } Console.WriteLine(""); Array.Resize(ref pallets, 3); Console.WriteLine($"Resizing 3 ... count: {pallets.Length}"); foreach (var pallet in pallets) { Console.WriteLine($"-- {pallet}"); } ``` Save your code file, and then run your code. When you run the code, you should see the following output: ```txt Clearing 2 ... count: 4 -- -- -- B12 -- A13 Resizing 6 ... count: 6 -- -- -- B12 -- A13 -- C01 -- C02 Resizing 3 ... count: 3 -- -- -- B12 ``` Notice that calling `Array.Resize()` didn't eliminate the first two null elements. Rather, it removed the last three elements. Notably, last three elements were removed even though they contained string values. #### Can you remove null elements from an array? If the `Array.Resize()` method doesn't remove empty elements from an array, is there another helper method that will do the job automatically? No. The best way to empty elements from an array would be to count the number of non-null elements by iterating through each item and increment a variable (a counter). Next, you would create a second array that is the size of the counter variable. Finally, you would loop through each element in the original array and copy non-null values into the new array. ### Recap Here's a few important ideas that you covered in this unit: - Use the `Clear()` method to empty the values out of elements in the array. - Use the `Resize()` method to change the number of elements in the array, removing or adding elements from the end of the array. - New array elements and cleared elements are null, meaning they don't point to a value in memory. --- ## Exercise ### Discover Split() and Join() As you continue your development work for a logistics company, you begin building a series of small applications. Combined, the applications take data from one partner's system, modify the data, then pass it to an internal system in the format it requires. To perform data transformation, you need to accept incoming data as a string, parse it into smaller data elements, then manipulate it to match different format required. How can you parse the string data into smaller data elements? #### String data type's Array methods The variables of type `string` have many built-in methods that convert a single string into either an array of smaller strings, or an array of individual characters. When processing data from other computer systems, sometimes it's formatted or encoded in a way that's not useful for your purposes. In these cases, you can use the `string` data type's Array methods to parse a string into an array. #### Use the `ToCharArray()` to reverse a `string` Delete or use the line comment operator `//` to comment out all of the code from the previous exercises. Update your code as follows: ```cs string value = "abc123"; char[] valueArray = value.ToCharArray(); ``` Here you use the `ToCharArray()` method to create an array of `char`, each element of the array has one character of the original string. #### Reverse, then combine the char array into a new string Next, you reverse the order of the chars in the array, then use the `Write` method to combine them back into a single output. Update your code as follows: ```cs string value = "abc123"; char[] valueArray = value.ToCharArray(); Array.Reverse(valueArray); string result = new string(valueArray); Console.WriteLine(result); ``` The expression `new string(valueArray)` creates a new empty instance of the `System.String` class (which is the same as the `string` data type in C#) and passes in the char array as a constructor. > Note > What is the new keyword? How is the `System.String` class related to the `string` data type in C#? What is a constructor? All great questions that unfortunately are out of scope for this module. You are recommended to keep learning about the .NET Class Library as well as classes and objects in C# to fully understand what is going on behind the scenes with this expression of cod e. For now, use a search engine and Microsoft Documentation to find examples you can use in situations like this where you know you want to perform a conversion but are not sure how to do it using C#. The Program.cs file must be saved before building or running the code. At the Terminal command prompt, to run your code, type `dotnet run` and then press Enter. ```txt 321cba ``` #### Combine all of the chars into a new comma-separated-value string using `Join()` Perhaps you need to separate each element of the char array using a comma, as is common when working with data that is represented as ASCII text. To do that, you'll comment out the line of code you added in Step 2 and use the String class' `Join()` method, passing in the char you want to delimit each segment (the comma) and the array itself. Update your code as follows: ```cs string value = "abc123"; char[] valueArray = value.ToCharArray(); Array.Reverse(valueArray); // string result = new string(valueArray); string result = String.Join(",", valueArray); Console.WriteLine(result); ``` Save your code file, and then run your code. You should see the following output: ```txt 3,2,1,c,b,a ``` `Split()` the comma-separated-value string into an array of strings To complete the code, you use the `Split()` method, which is for variables of type string to create an array of strings. Add the following lines of code at the bottom of the file: ```cs string[] items = result.Split(','); foreach (string item in items) { Console.WriteLine(item); } ``` Take a minute to review the previous code. The comma is supplied to `.Split()` as the delimiter to split one long string into smaller strings. The code then uses a `foreach` loop to iterate through each element of the newly created array of strings, `items`. Check that your code now appears as follows: ```cs string value = "abc123"; char[] valueArray = value.ToCharArray(); Array.Reverse(valueArray); // string result = new string(valueArray); string result = String.Join(",", valueArray); Console.WriteLine(result); string[] items = result.Split(','); foreach (string item in items) { Console.WriteLine(item); } ``` When you run the code, you'll see the following output: ```txt 3,2,1,c,b,a 3 2 1 c b a ``` The items array created using `string[] items = result.Split(',');` is used in the `foreach` loop and displays the individual characters from the original `string` contained in the value variable. ### Recap Here's a few things to remember when working with strings and arrays: - Use methods like `ToCharArray()` and `Split()` to create an array - Use methods like `Join()`, or create a new string passing in an array of `char` to turn the array back into a single string --- ## Exercise ### Complete a challenge to reverse words in a sentence Code challenges reinforce what you've learned and help you gain some confidence before continuing on. Many times you'll need to combine several of the ideas covered in this module into a single solution. You should work to decompose a larger problem into lots of mini-problems, then use the various ideas in this module to solve each mini-problem. #### Write code to reverse each word in a message Update your code in the editor as follows: ```cs string pangram = "The quick brown fox jumps over the lazy dog"; ``` Write the code necessary to reverse the letters of each word in place and display the result. In other words, don't just reverse every letter in the variable pangram. Instead, you'll need to reverse just the letters in each word, but print the reversed word in its original position in the message. Your code must produce the following output: ```txt ehT kciuq nworb xof spmuj revo eht yzal god ``` > Important > This is a particularly difficult challenge. You will need to combine many of the concepts you learned in this exercise, including the use of the `Split()`, `ToCharArray()`, `Array.Reverse()`, and `String.Join()`. You'll also need to create multiple arrays, and at least one iteration statement. Good luck! Just keep decomposing the problem into small steps, then solve that particular step before moving to the next. Whether you get stuck and need to peek at the solution or you finish successfully, continue on to view a solution to this challenge. --- ## Exercise ### Complete a challenge to parse a string of orders, sort the orders and tag possible errors Data comes in many formats. In this challenge you have to parse the individual "Order IDs", and output the "OrderIDs" sorted and tagged as "Error" if they aren't exactly four characters in length. Add the following code to get the data for the challenge: ```cs string orderStream = "B123,C234,A345,C15,B177,G3003,C235,B179"; ``` Notice in the previous code, the `orderStream` variable contains a string of multiple Order IDs separated by commas Add code below the previous code to parse the "Order IDs" from the string of incoming orders and store the "Order IDs" in an array Add code to output each "Order ID" in sorted order and tag orders that aren't exactly four characters in length as "- Error" Save and run your code Your code must produce the following output: ```txt A345 B123 B177 B179 C15 - Error C234 C235 G3003 - Error ``` Whether you get stuck and need to peek at the solution or you finish successfully, continue on to view a solution to this challenge. --- ## Summary In this module, you completed exercises using helper methods to use arrays more effectively to: - Clear items in an array, learning the elements are set to null, using the `Array.Clear()` method. - Resize an array to add and remove elements using the `Array.Resize()` method. - Convert a string into an array using `String.Split()` specifying a string separator character to produce a value in the returned array. - Combine all of the elements of an array into a single string using the `String.Join()` method. The array helper methods allowed you to work flexibly with data in the applications. Without these features, arrays would be less useful.