Ruby – Dry Code with Map, Next and Reject

For example, we have this Channel class:

class Channel
  attr_reader :id, :name

  def initialize(id, name) 
    @id = id
    @name = name
  end
end

 

1.

What we have:

One list of objects:

current_channels = [Channel.new(1, ‘channel1’), Channel.new(2, ‘channel2’), Channel.new(3, ‘channel3’)]

Task: Get arrays of ids from this list.

1.1 Bad solution

current_channel_ids = []

current_channels.each do |channel|
  current_channel_ids << channel.id
end

1.2 Better solution using map

current_channel_ids = current_channels.map { |channel| channel.id }

1.3 Best solution using map

current_channel_ids = current_channels.map(&:id)

 

2.

What we have:

Two lists of objects:

current_channels = [Channel.new(1, ‘channel1’), Channel.new(2, ‘channel2’), Channel.new(3, ‘channel3’)]

need_to_be_assigned_channels = [ Channel.new(1, ‘channel1’), Channel.new(4, ‘channel4’)]

Task: Assign channels in need_to_be_assigned_channels to current_channels array and make sure there’re no two channels with identical id.

Solution:

Before each solution, get the an array of ids from current_channels:

current_channel_ids = current_channels.map(&:id)

2.1 Bad solution

need_to_be_assigned_channels.each do |channel|
  unless current_channel_ids.include?(channel.id)
    current_channels << channel
  end
end

2.2 Better solution using next

need_to_be_assigned_channels.each do |channel|
  next if current_channel_ids.include?(channel.id)
  current_channels << channel
end

2.3 Best solution using reject

current_channels.concat(need_to_be_assigned_channels.reject { |assigned_channel| current_channel_ids.include?(assigned_channel.id) })

 

3.

What we have:

Two lists of objects:

current_channels = [Channel.new(1, ‘channel1’), Channel.new(2, ‘channel2’), Channel.new(3, ‘channel3’)]

need_to_be_deleted_channels = [ Channel.new(1, ‘channel1’), Channel.new(3, ‘channel3’)]

Task: Delete channels from current_channels if the id matches one of the ids in  need_to_be_deleted_channels.

Solution:

Before each solution, get the an array of ids from current_channels:

current_channel_ids = current_channels.map(&:id)

3.1 Bad solution

current_channels.each do |channel|
  next unless need_to_be_deleted_channel_ids.include?(channel.id)
  current_channels.delete(channel)
end

3.2 Best solution using delete_if

current_channels.delete_if { |channel| need_to_be_deleted_channel_ids.include?(channel.id) }

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s