From 16858922b6820a744f39b5f44f28f7b92d85becc Mon Sep 17 00:00:00 2001 From: TheSeagullDev <67653706+TheSeagullDev@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:46:53 -0400 Subject: [PATCH] Fix linting errors in 3 files --- ruby/basic_ruby/basic_enumerable_methods.md | 73 +++++++++++-------- .../predicate_enumerable_methods.md | 26 +++++-- 2 files changed, 62 insertions(+), 37 deletions(-) diff --git a/ruby/basic_ruby/basic_enumerable_methods.md b/ruby/basic_ruby/basic_enumerable_methods.md index 707a186c227..4f29522a41c 100644 --- a/ruby/basic_ruby/basic_enumerable_methods.md +++ b/ruby/basic_ruby/basic_enumerable_methods.md @@ -1,4 +1,5 @@ ### Introduction + In previous lessons, you learned about loops as well as arrays and hashes. You will soon discover that you'll have to do so much iterating (looping or repeating something several times) over collections as a developer that it will make you dizzy. Remember the **DRY (Don't Repeat Yourself)** approach to programming that we talked about in the lesson on Methods? Well, Ruby keeps iterating DRY through something called enumerables. **Enumerables** are a set of convenient built-in methods in Ruby that are included as part of both arrays and hashes. There are some iteration patterns that you'll find yourself doing again and again, such as transforming, searching for, and selecting subsets of elements in your collections. Enumerables were designed to make implementing these iteration patterns (and therefore your life as a developer) much, much easier. @@ -19,6 +20,7 @@ This section contains a general overview of topics that you will learn in this l - Explain what a bang method is and why it is or is not considered best practice. ### Life before enumerables + Let's say that you wanted to make an invite list for your birthday using your `friends` array but that you don't want to invite your friend Brian because he's a bit of a nutcase at parties and always drinks way too much. With the loops you've learned so far, you might do something like this: @@ -35,7 +37,8 @@ end invited_list #=> ["Sharon", "Leo", "Leila", "Arun"] ``` -_Warning:_ The __do__ is optional in a for loop in Ruby and may cause issues if used in IRB + +_Warning:* The **do** is optional in a for loop in Ruby and may cause issues if used in IRB That's not too hard, but imagine having to do that for every party you host from now until the end of time! It might be easier to just stop hanging out with Brian. @@ -60,6 +63,7 @@ friends.reject { |friend| friend == 'Brian' } You just cut down what was previously an 8 line program down to 2 lines. Amazing! Imagine all the time you'll save sorting your invite lists now. ### The each method + `#each` is the granddaddy of the enumerable methods. It's a bit like Chuck Norris: it can do anything. As you'll see throughout this lesson, though, just because you can use `#each` to do just about anything doesn't mean it's always the best or most efficient tool for the job. Calling `#each` on an array will iterate through that array and will yield each element to a code block, where a task can be performed: @@ -80,10 +84,10 @@ friends.each { |friend| puts "Hello, " + friend } Let's break down this syntax: -* `friends` is the array that contains strings of your friends' names. -* `.each` is the enumerable method you are calling on your `friends` array. -* `{ |friend| puts "Hello, " + friend }` is a **block**, and the code inside this block is run for each element in your array. Because we have 5 friends in our array, this block will be run 5 times, once with each of the 5 elements. -* Within the block, you'll notice that we have `|friend|`, which is known as a **block variable**. This is the element from your array that the block is currently iterating over. You can use any variable name that you find helpful here; in this example, we could have used `|x|`, but `|friend|` is more descriptive of what each element is. In the first iteration, the value of `|friend|` will be `'Sharon'`; in the second iteration, its value will be `'Leo'`; in the third, `'Leila'`; and so on until it reaches the end of the array. +- `friends` is the array that contains strings of your friends' names. +- `.each` is the enumerable method you are calling on your `friends` array. +- `{ |friend| puts "Hello, " + friend }` is a **block**, and the code inside this block is run for each element in your array. Because we have 5 friends in our array, this block will be run 5 times, once with each of the 5 elements. +- Within the block, you'll notice that we have `|friend|`, which is known as a **block variable**. This is the element from your array that the block is currently iterating over. You can use any variable name that you find helpful here; in this example, we could have used `|x|`, but `|friend|` is more descriptive of what each element is. In the first iteration, the value of `|friend|` will be `'Sharon'`; in the second iteration, its value will be `'Leo'`; in the third, `'Leila'`; and so on until it reaches the end of the array. What if the block you want to pass to a method requires more logic than can fit on one line? It starts to become less readable and looks unwieldy. For multi-line blocks, the commonly accepted best practice is to change up the syntax to use `do...end` instead of `{...}`: @@ -134,6 +138,7 @@ friends.each { |friend| friend.upcase } You might expect this to return `['SHARON', 'LEO', 'LEILA', 'BRIAN', 'ARUN']`, but you'd be wrong---dead wrong. It actually returns the original array you called `#each` on. You're *still* not invited, Brian. ### The each_with_index method + This method is nearly the same as `#each`, but it provides some additional functionality by yielding two **block variables** instead of one as it iterates through an array. The first variable's value is the element itself, while the second variable's value is the index of that element within the array. This allows you to do things that are a bit more complex. For example, if we only want to print every other word from an array of strings, we can achieve this like so: @@ -151,6 +156,7 @@ fruits.each_with_index { |fruit, index| puts fruit if index.even? } Just like with the `#each` method, `#each_with_index` returns the original array it's called on. ### The map method + Remember when we tried to use `#each` to write all of your friends' names in all caps? For reference, this is the code that we tried: ```ruby @@ -213,6 +219,7 @@ salaries.map { |salary| salary - 700 } Whenever you want to return a new array with the results of running your block of code, `#map` is the method for you! ### The select method + You've already seen the `#select` method in action at the beginning of this lesson in our quest to make Brian an outcast. The `#select` method (also called `#filter`) passes every item in an array to a block and returns a new array with only the items for which the condition you set in the block evaluated to `true`. @@ -254,6 +261,7 @@ responses.select { |person, response| response == 'yes'} Looks like only Sharon and Arun can go. You're going to need more people for a good party. Sounds like it's time for you to reluctantly call Brian, who you know will bring a batch of his awful home-brewed IPA. Maybe his last batch has gotten better? ### The reduce method + The `#reduce` method (also called `#inject`) is possibly the most difficult-to-grasp enumerable for new coders. The general idea is that it takes an array or hash and reduces it down to a single object. You should use `#reduce` when you want to get an output of a single value. A classic example of when `#reduce` is useful is obtaining the sum of an array of numbers. First, let's explore how we would achieve this using `#each`: @@ -282,8 +290,8 @@ Whoa! What?! There's a lot happening here, so let's walk through what it's doing The first block variable in the `#reduce` enumerable (`sum` in this example) is known as the **accumulator**. The result of each iteration is stored in the accumulator and then passed to the next iteration. The accumulator is also the value that the `#reduce` method returns at the end of its work. By default, the initial value of the accumulator is the first element in the collection, so for each step of the iteration, we would have the following: 1. Iteration 0: sum = 5 + 6 = 11 - 2. Iteration 1: sum = 11 + 7 = 18 - 3. Iteration 2: sum = 18 + 8 = 26 + 1. Iteration 1: sum = 11 + 7 = 18 + 1. Iteration 2: sum = 18 + 8 = 26 We can also set a different initial value for the accumulator by directly passing in a value to the `#reduce` method. @@ -333,21 +341,22 @@ hundreds["new"] #=> 99 Now that we know that this new hash with a default value of `0` is our accumulator (which is called `result` in the code block), let's see what happens in each iteration: 1. Iteration 0: - * result = {} - * Remember, this hash already has default values of `0`, so `result["Bob's Dirty Burger Shack"] == 0` and `result["St. Mark's Bistro"] == 0` - 2. Iteration 1: - * The method runs `result["Bob's Dirty Burger Shack"] += 1` - * result = {"Bob's Dirty Burger Shack" => 1} - 3. Iteration 2: - * The method runs `result["St. Mark's Bistro"] += 1` - * result = {"Bob's Dirty Burger Shack" => 1, "St. Mark's Bistro" => 1} - 4. Iteration 3: - * The method runs `result["Bob's Dirty Burger Shack"] += 1` - * result = {"Bob's Dirty Burger Shack" => 2, "St. Mark's Bistro" => 1} + - result = {} + - Remember, this hash already has default values of `0`, so `result["Bob's Dirty Burger Shack"] == 0` and `result["St. Mark's Bistro"] == 0` + 1. Iteration 1: + - The method runs `result["Bob's Dirty Burger Shack"] += 1` + - result = {"Bob's Dirty Burger Shack" => 1} + 1. Iteration 2: + - The method runs `result["St. Mark's Bistro"] += 1` + - result = {"Bob's Dirty Burger Shack" => 1, "St. Mark's Bistro" => 1} + 1. Iteration 3: + - The method runs `result["Bob's Dirty Burger Shack"] += 1` + - result = {"Bob's Dirty Burger Shack" => 2, "St. Mark's Bistro" => 1} Note that this example returns a hash with several `key => value` pairs. So even though the result is more complicated, `#reduce` still just returns one object, a hash. ### Bang methods + Earlier, we mentioned that enumerables like `#map` and `#select` return new arrays but don't modify the arrays that they were called on. This is by design since we won't often want to modify the original array or hash and we don't want to accidentally lose that information. For example, if enumerables did mutate the original array, then using `#select` to filter out Brian from our invitation list would *permanently* remove him from our friends list. Whoa! That's a bit drastic. Brian may be a nutcase at parties, but he's still our friend. To see this principle in action, let's go back to an earlier example where we wrote each of our friends' names in all caps: @@ -383,6 +392,7 @@ As you'll recall from the Methods lesson, **bang methods** can be easily identif It's best practice to avoid using these methods, however, as you or a future developer working on your code may need the original version. Remember that violent psychopath who you should expect will end up maintaining your code? Keep that in mind when making the decision to use bang methods. ### Return values of enumerables + So if it's not a good idea to use bang methods but we need to reuse the result of an enumerable method throughout our program, what can we do instead? One option is to put the result of an enumerable method into a local variable: @@ -416,24 +426,27 @@ invited_friends(friends) ``` ### Assignment +