1. 程式人生 > >用map, next 和 reject 簡化程式碼(ruby)

用map, next 和 reject 簡化程式碼(ruby)

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) }