mirror of
https://github.com/ro31337/rubyisforfun
synced 2024-11-16 19:50:09 +01:00
Save
This commit is contained in:
parent
99e1a1bfdd
commit
dfd61fffd8
3 changed files with 177 additions and 0 deletions
98
manuscript/040.txt
Normal file
98
manuscript/040.txt
Normal file
|
@ -0,0 +1,98 @@
|
|||
## Arrays
|
||||
|
||||
Array is just a set of data. For example, array of tenants living in apartment building. Or array of numbers where each number has some meaning (for example, employee salary). Or array of objects: each object represents employee with multiple properties like salary, age, name, and so on.
|
||||
|
||||
In Ruby each element in array can be of different type. In other words, arrays look like a bucket where we can put apples, pears, some tape recordings, and a couple of aircraft ships. But usually arrays are homogeneous: all items (or "elements") are of the same type.
|
||||
|
||||
But the question is why do we need arrays? Why would we need to put something into array? The question is quite simple: arrays are useful, because they represent a _set_ of some data and we can perform bulk operations over this data. Let's say we have a list of visited cities:
|
||||
|
||||
```ruby
|
||||
arr = ['San Francisco', 'Moscow', 'London', 'New York']
|
||||
```
|
||||
|
||||
We initialized array with four elements inside of type _String_. Ruby knows it's array because we used square brackets for array definition. We can perform variety of different useful operations over this data. For example, get the number of elements (visited cities):
|
||||
|
||||
```
|
||||
$ irb
|
||||
...
|
||||
> arr.size
|
||||
=> 4
|
||||
```
|
||||
|
||||
Or just sort array in alphabetical order:
|
||||
|
||||
```
|
||||
$ irb
|
||||
...
|
||||
> arr.sort
|
||||
=> ["London", "Moscow", "New York", "San Francisco"]
|
||||
```
|
||||
|
||||
Or we can _iterate_ over array (walk over each element):
|
||||
|
||||
```ruby
|
||||
arr = ['San Francisco', 'Moscow', 'London', 'New York']
|
||||
arr.each do |word|
|
||||
puts "Word #{word} has #{word.size} letters"
|
||||
end
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
Word San Francisco has 13 letters
|
||||
Word Moscow has 6 letters
|
||||
Word London has 6 letters
|
||||
Word New York has 8 letters
|
||||
```
|
||||
|
||||
And nothing prevents developer from defining empty array:
|
||||
|
||||
```ruby
|
||||
arr = []
|
||||
```
|
||||
|
||||
But why would we need an empty array? For the same purpose we need empty bucket -- to put something inside on later steps. There are many ways to put something into array, but there are two standard ways:
|
||||
|
||||
* `arr.push(123)` - method `push` also implemented in some other languages (like JavaScript), and some programmers prefer this way.
|
||||
* `arr << 123` - double arrow shows to _where_ we want to put something.
|
||||
|
||||
And trivial phonebook program could look like this:
|
||||
|
||||
{title="Trivial Phone Book Program, version 1", lang=ruby, line-numbers=on}
|
||||
```ruby
|
||||
arr = []
|
||||
|
||||
loop do
|
||||
print 'Type name and number (empty string to finish): '
|
||||
entry = gets.chomp
|
||||
break if entry.empty?
|
||||
arr << entry
|
||||
end
|
||||
|
||||
puts 'Your phone book:'
|
||||
|
||||
arr.each do |element|
|
||||
puts element
|
||||
end
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
Type name and number (empty string to finish): Saul 12345
|
||||
Type name and number (empty string to finish): Mummy (555) 111-22-33
|
||||
Type name and number (empty string to finish): Honey (555) 12345
|
||||
Type name and number (empty string to finish): Honey 2 (555) 98765
|
||||
Type name and number (empty string to finish):
|
||||
Your phone book:
|
||||
Saul 12345
|
||||
Mummy (555) 111-22-33
|
||||
Honey (555) 12345
|
||||
Honey 2 (555) 98765
|
||||
```
|
||||
|
||||
Of course, this phone book application is minimalistic and lacks lots of features, program doesn't save any data to disk, no search by name or phone number, but it works! We were able to save data temporarily and show the list of contacts on the screen. We can invoke `arr.sort` to sort all elements in our phonebook, so result looks much better!
|
||||
|
||||
X> ## Exercise 1
|
||||
X> Run this program and think about adding `arr.sort` line. Where would you put it?
|
76
manuscript/041.txt
Normal file
76
manuscript/041.txt
Normal file
|
@ -0,0 +1,76 @@
|
|||
## Few Words About "Each"
|
||||
|
||||
Array is [represented](https://ruby-doc.org/core-2.5.2/Array.html) by _Array_ type and this type implements method `each`. You are already familiar with this method when we were performing action over each element. Technically, method `each` _accepts block_. As we mentioned before, you can pass block to any method, and further behavior of a program depends on what's "under the hood" of this method.
|
||||
|
||||
So that method `each` runs what's inside the block for each element of array. In other words, it runs (usually tiny) sub-program for every item:
|
||||
|
||||
```ruby
|
||||
arr.each do |item|
|
||||
# here we have sub-program
|
||||
# it may have multiple lines
|
||||
end
|
||||
```
|
||||
|
||||
Or it can be done with one line:
|
||||
|
||||
```ruby
|
||||
arr.each { |item| ...here we have 1-line sub-program... }
|
||||
```
|
||||
|
||||
Examples above show that blocks accept parameters (`item` in our case). This parameter comes from `each` method, and it's just next element of array. Everything between `do` and `end` (or between `{` and `}`) is block. This way ruby implements iteration over array (or "array iteration", "iteration over each element of array", "array traversal").
|
||||
|
||||
We can specify any name as parameter. In example from previous chapter (iteration over cities) we used `word` as parameter name. Phone book application has `element` as parameter name. And in this chapter we have `item`. The only rule here is parameter name should be understandable for you and your team (ideally, tools like Rubocop must be also okay with that).
|
||||
|
||||
Method `each` looks like calling your own method:
|
||||
|
||||
```ruby
|
||||
def my_method(word)
|
||||
puts "Word #{word} has #{word.size} letters"
|
||||
end
|
||||
```
|
||||
|
||||
Compare it with `each`:
|
||||
|
||||
```ruby
|
||||
arr.each do |word|
|
||||
puts "В слове #{word} #{word.size} букв"
|
||||
end
|
||||
```
|
||||
|
||||
It's sad that in Ruby you can't pass the name of a method to `each`:
|
||||
|
||||
```ruby
|
||||
arr.each my_method
|
||||
```
|
||||
|
||||
It would be a nice language feature. Note: actually, you can write the similar code, but 1) not exactly this way 2) with some limitations 3) nobody doesn't do it anyway.
|
||||
|
||||
Method `each` is also implemented in some other types. Iteration over something is operation which is pretty often used by programmers here and there, and you'll see iteration in some not very obvious places. For example, iteration over string (object of _String_ type):
|
||||
|
||||
```
|
||||
$ irb
|
||||
> 'hello'.each_char { |x| puts x }
|
||||
h
|
||||
e
|
||||
l
|
||||
l
|
||||
o
|
||||
```
|
||||
|
||||
Method `each` for _Range_ type:
|
||||
|
||||
```ruby
|
||||
(1001..1005).each do |x|
|
||||
puts "I'm robot #{x}"
|
||||
end
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
I'm robot 1001
|
||||
I'm robot 1002
|
||||
I'm robot 1003
|
||||
I'm robot 1004
|
||||
I'm robot 1005
|
||||
```
|
|
@ -37,6 +37,9 @@
|
|||
037.txt
|
||||
038.txt
|
||||
039.txt
|
||||
040.txt
|
||||
041.txt
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue