Arrays are one of the basic constructs of programming. It appears everywhere and almost always when manipulating data we always need arrays to process. Therefore, mastering and successful manipulating array operations is an extremely important and necessary, especially for beginners like me.
Here I would like to introduce some array processing techniques that are considered quite popular and you need to understand it thoroughly, these are the first steps to becoming a true Ruby dev.
Each
Browse through the elements in the array and manipulate them:
1 2 3 4 5 | [1, 2, 3].each { |n| puts "Current number is: #{n}" } Current number is: 1 Current number is: 2 Current number is: 3 |
Nothing much to say to each
. The only small note is that each
will luôn luôn trả về mảng gốc
matter how you transform.
1 2 3 | result = [1, 2, 3].each{|e| e + 2} => [1, 2, 3] |
Map / Collect
Map and Collect are alias_method of each other so when using any guy, I see that most people use map
more, maybe it's more concise than collect
Nothing is easier to understand than going straight to the example:
1 2 3 4 | array = [1,2,3] array.map { |n| n * 2 } => [2, 4, 6] |
If you want to change the original array always use map!
.
When you first started with ruby, I bet most of you use each
as the main right? Try the following simple code
1 2 3 | user_ids = [] users.each { |user| user_ids << user.id } |
… you can simplify by using the map
only takes 1 line only:
1 2 | user_ids = users.map { |user| user.id } |
Or even better and faster ( better and faster
):
1 2 | user_ids = users.map(&:id) |
Pinch the skirt, map (hoặc collect)
will return the new array has been processed, use the map
make your code cleaner.
Select and Detect
.select
allows you to "search" for elements in the array. You need to include .select
a conditional statement that returns true or false since it will help you know whether or not the elements you want to search in the array are.
.detect
is similar to .select
but instead of removing all the elements that satisfy the screen, .detect
only takes the first guy (only 1 guy)
Let's try, for example, retrieving even parts in an array ( .select
we don't know .select
):
1 2 3 | even_numbers = [1, 2, 3, 5, 4].map{|element| element if element.even?} # [nil, 2, nil, nil, 4] even_numbers = even_numbers.compact # [2, 4] |
Using .map
to get even guys but in return you give birth to nil guys, so I need to use the compact
function to get rid of nil guys, now we have what we need but handle it seems a bit cumbersome.
1 2 3 | even_numbers = [1, 2, 3, 5, 4].select{|element| element if element.even?} # [2, 4] first_even_numbers = [1, 2, 3, 5, 4].select{|element| element if element.even?} # [2] |
Ruby gave your teeth to you already! Only a simple line of code, easy to understand then what are you waiting for: v
Bonus: better and faster
1 2 3 | [1, 2, 3, 4, 5].select(&:even?) [1, 2, 3, 4, 5].detect(&:even?) |
Note: So .select
retrieves all the .select
who qualify. .detect
only retrieve the first guy that meets the conditions.
By the way, I would like to introduce the .compact
function to help remove nil
elements in a memory array
Reject
.reject
the complete opposite of .select
. Instead of taking out what we need (ie .select
), we will remove the elements that satisfy the set.
1 2 3 4 | array = [1, 2, 3, 5, 4] array.reject{|number| number < 3} => [3, 4, 5] |
Since the above example can see, with .select
will retrieve the .select
from <3 (ie [1, 2]), then .reject
is to remove the <3 elements (ie [3, 4, 5] ).
.select
, when you want to get what you need, use .select
, when you want to remove unwanted parts, use .reject
.
Reduce
Reduce has a more complex structure than other array processing methods, but in return it is often used quite simply in ruby, mainly for the calculation of elements in the array and then returned. The results have just finished.
Try with a simple example: Calculate the sum of the elements in an array.
1 2 3 4 | array = [1, 2, 3] array.reduce{|sum, x| sum + x} => 6 |
We can also manipulate the String array in the same way:
1 2 3 4 | array = ['amber', 'scott', 'erica'] array.reduce{|sum, name| sum + name} => "amberscotterica" |
As a final note about .reduce
, sometimes the data you manipulate is old data (not empty or 0), you need to pass an argument to initialize the original value:
1 2 3 4 5 6 | array = [{weekday: 'Monday', pay: 123}, {weekday: 'Tuedsay', pay: 244}] array.reduce(0) {|sum, day| sum + day[:pay]} => 367 array.reduce(100) {|sum, day| sum + day[:pay]} => 467 |
Join
.join
is really useful when working with arrays, especially in relation to String
1 2 3 | cars.map{|car| car[:type]}.join(', ') => "porsche, mustang, prius" |
.join
very similar to .reduce
except that it has a "super clean" owl. .join
needs to pass an argument – which will connect the elements together into a string.
1 2 3 4 5 | cars.join(', ') => "{:type=>"porsche", :color=>"red"}, {:type=>"mustang", :color=>"orange"}, {:type=>"prius", :color=>"blue"}" events.join(', ') => "#<Event:0x007f9beef84a08>, #<Event:0x007f9bf0165e70>, #<Event:0x007f9beb5b9170>" |
Why not combine methods together
Now we can still use the knowledge above to handle it at the same time.
We have an array of 10 working days, each day corresponding to 1 task and the estimated time of each task is random. Now I want to retrieve the total time of all tasks with the condition that ignoring tasks with estimates greater than 30 minutes as well as tasks with estimates less than 5 minutes:
1 2 3 4 5 6 7 8 | days = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] days.map{|day| day.odd? ? {task: 'dishes', minutes: Random.rand(20)} : {task: 'sweep', minutes: Random.rand(20)}} .select{|task| task[:minutes] < 30} .reject{|task| task[:minutes] < 5} .reduce(0) {|sum, task| sum + task[:minutes]} |
The above example may not seem very relevant, but the main purpose here is that we know how to combine methods together.
P / S: What ? :
may be strange for some of you don't know, it's the trinity operator is an abbreviation of if-else, in this case due to the simple problem, so I use it, but for the case complex logic, then I advise you not to use.
Bonus
sample
I have an array of integers, what do I want to get out of any number?
1 2 3 4 | [1, 2, 3][rand(3)] [1, 2, 3].shuffle.first [1, 2, 3].sample |
Use .sample
to make your code more .sample
.
slice
This function helps you clone data from a given array, you just need to specify the starting index value and the ending index you want to clone:
1 2 3 4 | sharks = ["Tiger", "Great White", "Hammerhead", "Angel"] sharks[1,2] # ["Great White", "Hammerhead"] sharks.slice(1,2) # ["Great White", "Hammerhead"] |
include?
Help you check if your input is in a given data array
1 2 3 4 | sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] sharks.include? "Tiger" # true sharks.include? "tiger" # false |
uniq?
Help you delete duplicates in array quickly
1 2 | [1,2,3,4,1,5,3].uniq # [1,2,3,4,5] |
Conclude
I hope this is helpful for some of you, not really all but enough for you to work the array smoothly. Many thanks for reading my article
Refer
https://www.freecodecamp.org/news/six-ruby-array-methods-you-need-to-know-5f81c1e268ce/
https://www.digitalocean.com/community/tutorials/how-to-use-array-methods-in-ruby