Reading notes on Enumerable of chapter ten (Collections central: Enumerable and Enumerator) of The Well-Grounded Rubyist by David A. Black.
Enumerable
p Enumerable.instance_methods(false).sort
Output:
[:all?, :any?, :chunk, :collect, :collect_concat, :count, :cycle, :detect, :drop, :drop_while, :each_cons, :each_entry, :each_slice, :each_with_index, :each_with_object, :entries, :find, :find_all, :find_index, :first, :flat_map, :grep, :group_by, :include?, :inject, :map, :max, :max_by, :member?, :min, :min_by, :minmax, :minmax_by, :none?, :one?, :partition, :reduce, :reject, :reverse_each, :select, :slice_before, :sort, :sort_by, :take, :take_while, :to_a, :zip]
Overriding each
class Countries
include Enumerable
def each
yield "Denmark"
yield "Finland"
yield "France"
yield "Spain"
yield "UK"
end
end
countries = Countries.new
countries.each do |c|
puts "Next country is #{c}"
end
Output:
Next country is Denmark
Next country is Finland
Next country is France
Next country is Spain
Next country is UK
Querying and Filtering
countries = ["Denmark", "Finland", "France", "Spain", "UK"]
p countries.include?("UK")
>> true
p countries.all? {|c| c =~ /a/}
>> false
p countries.any? {|c| c =~ /a/}
>> true
p countries.one? {|c| c =~ /U/ }
>> true
p countries.first
>> "Denmark"
p countries.find {|c| c.start_with?("F")}
>> "Finland"
p countries.find_all {|c| c.start_with?("F")}
>> ["Finland", "France"]
p countries.select {|c| c.include?("a")}
>> ["Denmark", "Finland", "France", "Spain"]
p countries.reject {|c| c.include?("a")}
>> ["UK"]
p countries.grep(String)
>> ["Denmark", "Finland", "France", "Spain", "UK"]
Grouping
countries = ["Denmark", "Finland", "France", "Spain", "UK"]
p countries.group_by {|c| c.size}
Output:
{7=>["Denmark", "Finland"], 6=>["France"], 5=>["Spain"], 2=>["UK"]}
Partitioning
countries = ["Denmark", "Finland", "France", "Spain", "UK"]
result = countries.partition {|c| c.size > 5}
p result
p "There are #{result[1].size} countries with 5 or less characters."
[["Denmark", "Finland", "France"], ["Spain", "UK"]]
"There are 2 countries with 5 or less characters."
Take and Drop
countries = %w{Denmark Finland France Spain UK}
# Take
p countries.take(2)
>> ["Denmark,", "Finland,"]
p countries.take_while {|c| c.size > 5}
>> ["Denmark", "Finland", "France"]
# Drop
p countries.drop(2)
>> ["France,", "Spain,", "UK"]
p countries.drop_while {|c| c.size > 5}
>> ["Spain", "UK"]
Min, Max and MinMax
countries = %w{France Finland UK Denmark Spain}
p countries.min
>> "Denmark"
p countries.min_by {|c| c.size}
>> "UK"
p countries.max
>> "UK"
p countries.max_by {|c| c.size}
>> "Finland"
p countries.minmax
>> ["Denmark", "UK"]
p countries.minmax_by {|c| c.size}
>> ["UK", "Finland"]
each_with_index
countries = %w{Denmark Finland France Spain UK}
countries.each_with_index {|c, i| puts "#{i}. #{c}"}
Output:
0. Denmark
1. Finland
2. France
3. Spain
4. UK
each_slice and each_cons
countries = %w{Denmark Finland France Spain UK}
countries.each_slice(2) {|slice| p slice}
Output:
["Denmark", "Finland"]
["France", "Spain"]
["UK"]
countries = %w{Denmark Finland France Spain UK}
countries.each_cons(2) {|cons| p cons}
Output:
["Denmark", "Finland"]
["Finland", "France"]
["France", "Spain"]
["Spain", "UK"]
cycle
The cycle method simply loops through the elements of a collection. If the number of loops to go through is not passed in, we end up with an infinite loop.
countries = %w{EE I}
countries.cycle(2) do |c|
print c + " "
end
print "O"
inject
The inject method applies an accumulator function over a collection.
text = %w{Lorem ipsum dolor sit amet}
p text
>> ["Lorem", "ipsum", "dolor", "sit", "amet"]
puts text.inject("") {|acc, word| acc + word + " "}
>> Lorem ipsum dolor sit amet
Note: the reduce method can also be used in place of inject.
map
The map method always return a new array instance with the same size of the input array.
countries = ["France", "Spain", "UK"]
p countries.map {|c| c.upcase}
>> ["FRANCE", "SPAIN", "UK"]
To map directly on the receiver simply use the bang version:
countries = %w(France Spain UK)
puts "BEFORE: #{countries}"
>> BEFORE: ["France", "Spain", "UK"]
countries.map! {|c| c.upcase}
puts "AFTER: #{countries}"
>> AFTER: ["FRANCE", "SPAIN", "UK"]