5 less used Enumerators of Ruby

The reason behind this blog post is pretty simple - I wanted to pick apart some of the goodies of Enumerable module and have a reference for people who use #each all the time in their code.

Let's partition

When you need to split collection in two parts, there is a #partition method for that. Let's say we want to partition our collection of animals and humans in two parts. What parts you will ask? Humans and animals of course:

class Animal
	def is_animal?
    	true
    end
end
class Human
	def is_animal?
    	false
    end
end


[Animal.new, Animal.new, Human.new, Human.new, Animal.new].partition { |c| c.is_animal? }

#=> [[#<Animal:0x007fb019830d08>, #<Animal:0x007fb019830ce0>, #<Animal:0x007fb019830bf0>], [#<Human:0x007fb019830c68>, #<Human:0x007fb019830c18>]]

Cool, we have a collection of animals and collection of humans! That sounded weird, but that's ok - It's Ruby. Let's move on to next enumerator.

Each with object you say?

Let's say we want to iterate a collection, but we want to drag single object with us inside of block. In our case we will have a Person instance and it will have
a #greet method. (How classic). So the greeter will be a string that will be passed along for each element of collection. Enough words, let's see example:

class Person
	def initialize(name)
    	@name = name
    end
	def greet(greeter)
    	puts "#{greeter} #{@name}"
    end
end
[Person.new("Peter"), Person.new("Meg"), Person.new("Louis")].each_with_object("Hello") { |i, a|  i.greet(a)} #=>
# Hello Peter
# Hello Meg
# Hello Louis

Finding maximal price

Okay, we have a list of products and we need to return the priciest product we have. This method will make our sales team happy.

class Product
	def initialize(price)
    	@price = price
    end
	attr_reader :price
end
[Product.new(100), Product.new(120), Product.new(1000)].max_by(&:price)
=> #<Product:0x007fb019861228 @price=1000>

Sometimes I am so glad that computer does all the heavy lifting for me :)

What about lowest and highest price?

Same stuff. A sales guy comes to you and says - We need to find product with a lowest and highest price. No problemo. It's simple to do in Ruby:

class Product
	def initialize(price)
    	@price = price
    end
	attr_reader :price
end
[Product.new(100), Product.new(120), Product.new(1000)].minmax_by(&:price)
=> [#<Product:0x007fb01887a418 @price=100>, #<Product:0x007fb01887a3c8 @price=1000>]

First element of returned array will be the product with smallest price and second element will be with highest.

Take while we can!

Let's play cops and robbers. We want to create a list of people that we want to rob. Our goal is to stop when we stumble upon a cop. Then we decide that it will be enough and go underground to create our evil plan. Let's do it with help of Ruby!

class Person
	def can_be_robbed?
    	true
    end
end
class Cop
	def can_be_robbed?
    	false
    end
end

[Person.new, Person.new, Cop.new, Person.new].take_while(&:can_be_robbed?)

=> [#<Person:0x007fa21a848848>, #<Person:0x007fa21a848820>]

Only two people? Meh, not worth it. Let's figure out something else.

Conclusion

I hope you found this blog post interesting or at least funny. Enumerable has a ton of methods that can very useful, so I suggest you take a look at it and you might find what you need.

Janis Miezitis

Read more posts by this author.

Subscribe to Janis Miezitis personal blog

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!