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 +
1. Read through the Ruby Explained article on [Map, Select, and Other Enumerable Methods](https://www.eriktrautman.com/posts/ruby-explained-map-select-and-other-enumerable-methods). - 2. Follow along with this [How to Use The Ruby Map Method](https://www.rubyguides.com/2018/10/ruby-map-method/) tutorial from Ruby Guides. - 3. Follow along with this [Reducing Enumerable](https://medium.com/@baweaver/reducing-enumerable-part-one-the-journey-begins-ddc1d4108490) article by Brandon Weaver. - 4. Complete the basic enumerable exercises from the [ruby-exercises repo](https://github.com/TheOdinProject/ruby-exercises) that you previously cloned. + 1. Follow along with this [How to Use The Ruby Map Method](https://www.rubyguides.com/2018/10/ruby-map-method/) tutorial from Ruby Guides. + 1. Follow along with this [Reducing Enumerable](https://medium.com/@baweaver/reducing-enumerable-part-one-the-journey-begins-ddc1d4108490) article by Brandon Weaver. + 1. Complete the basic enumerable exercises from the [ruby-exercises repo](https://github.com/TheOdinProject/ruby-exercises) that you previously cloned. +
### Knowledge check -This section contains questions for you to check your understanding of this lesson. If you're having trouble answering the questions below on your own, review the material above to find the answer. - - * What does the `#each` method do? What does it return? - * What does the `#each_with_index` method do? - * What does the `#map` method do? - * What does the `#select` method do? - * What does the `#reduce` method do? - * When should you use `do...end` around a code block versus `{...}`? - * Why should you avoid using the bang methods of enumerables? + +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. + +- [What does the `#each` method do? What does it return?](#the-each-method) +- [What does the `#each_with_index` method do?](#the-each_with_index-method) +- [What does the `#map` method do?](#the-map-method) +- [What does the `#select` method do?](#the-select-method) +- [What does the `#reduce` method do?](#the-reduce-method) +- [When should you use `do...end` around a code block versus `{...}`?](#ruby-knowledge-check-do..end-vs-{...}) +- [Why should you avoid using the bang methods of enumerables?](#bang-methods) ### Additional resources diff --git a/ruby/basic_ruby/predicate_enumerable_methods.md b/ruby/basic_ruby/predicate_enumerable_methods.md index d7f3b9ee35a..9f4cce3c3fc 100644 --- a/ruby/basic_ruby/predicate_enumerable_methods.md +++ b/ruby/basic_ruby/predicate_enumerable_methods.md @@ -1,4 +1,5 @@ ### Introduction + In the previous lesson, you learned about some really handy enumerable methods like `#each`, `#map`, and `#select`. In this lesson, we're going to learn about *even more* enumerable methods! Woohoo! The party never ends here at The Odin Project! This time, we're focusing on a particular subset of enumerable methods: the **predicate enumerable methods**. You should recall from the Methods lesson that a predicate method is indicated by a question mark (`?`) at the end of the method name and returns either `true` or `false`. Again, we won't be going through all of the predicate enumerable methods, so be sure to have a look at the [Ruby docs](https://docs.ruby-lang.org/en/3.3/) to see what else [Enumerable](https://docs.ruby-lang.org/en/3.3/Enumerable.html) offers. @@ -16,6 +17,7 @@ This section contains a general overview of topics that you will learn in this l - Explain how the `#none?` method works. ### The include? method + The `#include?` method works exactly like you think it should. If we want to know whether a particular element exists in an array, we can use the `#include?` method. This method will return `true` if the element you pass as an argument to `#include?` exists in the array or hash; otherwise, it will return `false`. First, let's explore how we would achieve this with the `#each` method: @@ -48,8 +50,11 @@ end result #=> false ``` +
+ If you notice, there is a `break` statement in the `if` condition so that loop stops executing once the number is found. Otherwise it would still run over all numbers in the array which is not needed as we have already found the element. +
Using `#include?`, this code can be greatly simplified: @@ -76,6 +81,7 @@ invited_list.include?('Brian') ``` ### The any? method + You might also be able to guess what the `#any?` method does. It returns `true` if *any* elements in your array or hash match the condition within the block; otherwise, it will return `false`. Let's say we want to see if there is any number greater than 500 or less than 20 in an array of numbers. First, let's see how we could achieve this using `#each`. @@ -121,6 +127,7 @@ numbers.any? { |number| number < 20 } ``` ### The all? method + The `all?` method is also fairly intuitive. It only returns `true` if *all* the elements in your array or hash match the condition you set within the block; otherwise, it will return `false`. Let's say that we want to check whether all the words in our list are more than 3 characters or 6 characters long. First,let's see how we could achieve this using `#each`: @@ -170,6 +177,7 @@ fruits.all? { |fruit| fruit.length > 6 } Special note to keep in mind while debugging: `#all?` will return `true` by default unless the block returns `false` or `nil`. So if you call `#all?` on an empty array or hash (i.e., there are no elements for the block to evaluate), it will return `true`. ### The none? method + As you might expect, `#none?` returns `true` only if the condition in the block matches *none* of the elements in your array or hash; otherwise, it returns `false`. First, let's see how this could be achieved using `#each`. You'll notice that this approach is very similar to what we did for `#all?`. @@ -219,19 +227,23 @@ fruits.none? { |fruit| fruit.length > 6 } ``` ### Assignment +
+ 1. Read [How to Use Ruby Any, All, None, and One](https://www.rubyguides.com/2018/10/any-all-none-one/) for alternative explanations for predicate enumerables. - 2. Complete the predicate enumerable exercises from the [ruby-exercises repo](https://github.com/TheOdinProject/ruby-exercises) that you previously cloned. + 1. Complete the predicate enumerable exercises from the [ruby-exercises repo](https://github.com/TheOdinProject/ruby-exercises) that you previously cloned. +
### Knowledge check -This section contains questions for you to check your understanding of this lesson. If you're having trouble answering the questions below on your own, review the material above to find the answer. - * Why is there a question mark after some method names? - * What does the `#include?` method do? - * What does the `#any?` method do? - * What does the `#all?` method do? - * What does the `#none?` method do? +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. + +- [Why is there a question mark after some method names?](#introduction) +- [What does the `#include?` method do?](#the-include-method) +- [What does the `#any?` method do?](#the-any-method) +- [What does the `#all?` method do?](#the-all-method) +- [What does the `#none?` method do?](#the-none-method) ### Additional resources