Coder Social home page Coder Social logo

enumerators-readme's Introduction

Enumerators

Objectives

  1. Become familiar with some enumerators.
  2. Get comfortable reading the official Ruby documentation on enumerators.
  3. Understand the difference between .each and .collect.

Introduction

Enumerators allow for iterative actions on data structures, specifically over arrays and hashes.

A hash is another type of collection. It stores data in associated pairs, much like a dictionary stores a collection of words and their definitions. We'll be discussing hashes later on. For now, just keep in mind that all of the methods discussed here can be used on both arrays and hashes.

Enumerator methods allow us to iterate over every member of a collection and do something to each member of that collection.

Why do we need Enumerators?

Let's revisit our earlier example of Professor Snape's list of Hogwarts students. Professor Snape is having a bad day and he'd like to vent some of that frustration by turning each of his students into a frog. He therefore needs to perform a certain action on each student.

Let's take a look at our student array:

students = ["Harry Potter", "Ron Weasley", "Hermione Granger", "Draco Malfoy"]

Snape has written a method (okay, a spell) turn_into_frog that he needs to call on each student:

def turn_into_frog(student)
  puts "Poof! #{student} is a frog."
end

Without enumerators, Snape would have to call his method (cast his spell) once for every argument (student) that he wishes to perform it on (turn into a frog):

turn_into_frog(students[0]) 
turn_into_frog(students[1])
turn_into_frog(students[2])
...

This approach has a number of serious drawbacks:

  • We are repeating ourselves on every line.
  • We need to know exactly how many students are in the array in order to operate on each and every one—and this could change!
  • What if we have a long list of students? Maybe Snape had a really bad day and he wants to turn everyone at Hogwarts into a frog! That would take forever.

Let's take a look at the same task using an enumerator:

students.each do |student|
  turn_into_frog(student)
end

This would successfully output:

"Poof! Harry Potter is a frog."
"Poof! Ron Weasley is a frog."
"Poof! Hermione Granger is a frog."
...

We went from many lines of code requiring us to grab each student one at a time, to just a few lines of code using our .each enumerator. Much better!

There are many enumerators available to you in Ruby, below are just a few. Read more about them in the official Ruby documentation.

.each

.each is a common enumerator method. The defining characteristic of .each is that its return value is the original data structure that it was called upon. Whatever is happening within the block will be evaluated as well.

Here's how .each works:

cool_nums = [1, 2, 3]

def change_nums(nums)
  nums.each do |x|
    puts x + 1
  end
end

change_nums(cool_nums)
2
3
4
#=> [1, 2, 3]

You can see that we are moving over every element in the array and executing the code in the do...end block for each element. That is exactly how enumerators work — we call them on a collection (i.e. array.each), pass that method call a block (i.e. code in between the do and the end), and that code passes each element into the block as a block argument.

.collect & .map

The .collect and .map methods are identical in functionality, and are similar to .each with one distinct difference: when you call .collect or .map on an array or hash a new array or hash object is returned, not the original one.

Let's take a look:

cool_nums = [1, 2, 3]

def change_nums(nums)
  nums.collect do |x| 
    x + 1
  end
end

change_nums(cool_nums)
#=> [2, 3, 4]

However, the original array does not change:

cool_nums
#=> [1, 2, 3]

.each vs. .collect

While these two are similar, there are times when it makes sense to use one over the other. If you need the return value of your method to be a collection that's been modified by what's happening within the block, then .collect is for you. Of course, it's quite possible to work with .each to accomplish that. One way is to make a new "placeholder" (array or hash) in memory and within the method definition, and then return that new placeholder as the last line of the method:

cool_nums = [1, 2, 3]

def change_nums(nums)
  new_count = []
  nums.each do |x|
    x += 1
    new_count << x
  end
  new_count
end

change_nums(cool_nums)
#=> [2, 3, 4]

But doesn't this code smell a little bit? It's a lot of lines to accomplish something that .collect does itself.

.select

The .select method returns a new collection containing all of the elements in the submitted collection for which the block's conditional is true:

cool_nums = [1, 2, 3, 4, 5]

def even_nums(nums)
  nums.select do |x|
    x.even?
  end
end

even_nums(cool_nums)
#=> [2, 4]

.find

The .find method is very similar to .select, but instead of collecting and returning all of the items for which a condition is true, .find returns only the first item for which it is true.

[1, 3, 5, 7].find do |num|
  num.odd?
end
  => 1

.delete_if

The .delete_if method, on the other hand, will delete from the collection any items that return true for a certain condition:

[1, 2, 4, 7].delete_if do |num|
  num.odd?
end

  => [2, 4]

.include?

You can use the .include? method to determine if a collection contains a specific element.

[1, 2, 3].include?(1)
  => true
  
[1, 2, 3].include?(4)
  => false

.any?

Calling .any? on a collection will return true if the code in the block (code between the do...end keywords or between the { } "curly braces") evaluates to true for any element in the collection. Let's take a look:

words = ["are", "any", "of", "these", "words", "longer", "than", "four", "letters"]

words.any? do |word|
  word.length > 4
end
  #=> true

The .any? method passes each element of the array it is called on to the code in between the do...end keywords. The length of each word gets compared to 4. Since there are two words in this collection that are longer than four letters, the line containing word.length > 4 returned true for those two words. Therefore, the entire method call of .any? on the array will return true.

Helpful Tools

As you move forward through this unit, you'll be required to use the above enumerable methods to complete labs and get RSpec tests passing. Rely on the Ruby Docs on Enumerators to help you. You can also use resources like Stack Overflow and good old fashioned googling to gain deeper understandings of how these methods work. Learning when and what to google is a valuable skill in programming, don't be afraid to use it.

Let's use an example. Say you are completing a lab that asks you to build a method that takes in an array as an argument and return the first item in the array that meets a certain condition. "Oh no!" you might think (having forgotten to refer back to this excellent Readme). But don't worry—googling something along the lines of "ruby method to return first item of collection that meets condition" is very likely to point you in the right direction. Go ahead and try it!

Resources

enumerators-readme's People

Contributors

ahimmelstoss avatar annjohn avatar damianb1451 avatar deniznida avatar drewprice avatar fislabstest avatar fs-lms-test-bot avatar markedwardmurray avatar sarogers avatar sgharms avatar shmulim avatar sofiajeanne avatar sophiedebenedetto avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

enumerators-readme's Issues

Missing punctuation?? Unclear explaination

This sentence isnt clear. It may be missing punctuation or may need to be reworded
Did you meant this -
pass that method**,** call a block (i.e. code in between the do and the end), and that code runs for every element in the collection.
Or Did you meant this_
pass that method call**,** a block (i.e. code in between the do and the end), and that code runs for every element in the collection.

Is call being used as a noun or a verb

missing some important enums

we should include find, reject, include, maybe mention some other common ones (inject?) that they can read more about.

follow up w/ repl challenge

notice students doing weird things to pass upcoming enum labs. maybe they need more baby steps to get comfortable using these methods.

let's make a repl challenge! (so excited for Learn repl)

Terminology

Including hashes in the discussion before defining them. Yes, they come along in the unit, but what is a hash? Either a quick definition of a hash at the top of this reading, or discussing enumeration in terms of "collections" vs. "arrays and hashes" might help with clarity. "Collections" is used intermittently already, so it might be worth pointing that "an array is one kind of collection, but there are other kinds as well."

Can we see an example of using .collect? We're shown what it's doing in terms of .each, but what does the .collect method call look like? Also, this section uses the term "scope" in its explanation, which is more advanced; maybe just explain it at as "within the method definition" vs. "in scope" at this point?

@SophieDeBenedetto

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.