如何在ruby / rails中合并两个列表并删除重复项?

时间:2013-06-02 00:34:39

标签: ruby-on-rails ruby

我有一个源对象

class Source

def ==(other)
  return false if self.url == nil || other == nil
  self.url == other.url
end

我有以下内容:

def self.merge_internal_and_external_sources(sources=[], external_sources=[])
    (sources + external_sources).uniq
end

我想合并这两个列表,如果它们已存在于源列表中,则开始从external_sources中踢出项目。我不确定如何雄辩地做到这一点?

我也尝试过:

sources | external_sources

但是这会产生一个结果而不会删除重复项,因为我的==比较想要在内部比较'url'属性?例如:

[src1] == [src2] # true
list = [src1] | [src2] 
list.size # 2

2 个答案:

答案 0 :(得分:5)

另一种选择是使用#uniq方法。但是,对于裸#uniq,同样的警告适用于#|方法:#hash#eql?按顺序用于测试相同的元素。

但是,uniq can take a block,所以

(sources + external_sources).uniq &:url
即使一个人懒得为相关课程定义#hash#eql?方法,也可以应用

答案 1 :(得分:3)

我不确定“merge”是什么意思(数组上没有#merge方法,只有哈希),但你可以这样简化代码:

merged = sources | external_sources

要使它适用于您的类,您还需要两个方法:#hash(实例哈希值,用于初步相等性筛选)和#eql?,用于确认相等:

class Source
  def hash
    url.hash + 1
  end
  # Or delegate it to the url:
  # require 'active_support/core_ext/module/delegation'
  # delegate :hash, to: :url

  def eql? other
    return false if url.nil? || other.url.nil?
    url == other.url
  end
end

#hash#eql?是每个班级应具备的基本设施。添加这些后,#|#&方法将开始在Source个实例的数组上运行。