如何在ruby中找到基于对象属性的两个数组的重叠

时间:2014-07-30 23:31:52

标签: ruby arrays

我对ruby比较新,所以我试图学习ruby最佳实践。我有两个数组array1array2。它们每个只包含一个类Animal,每个数组都保证是唯一的。我的Animal类除其他外还有一个color属性,它是一个字符串。我想要做的是Animal中的每个array1我希望array2中的所有动物都使用相同的颜色并将其移至array1。更详细的代码如下所示:

for x from 0 to array1.size
  for y in array2
    if(array1[x].color == y.color)
      array1 << y
      array2.delete(y)
    end
  end
end

但是看到红宝石是一种非常简洁的语言,我觉得有一个更优雅的解决方案来做到这一点。这样做最红宝石的方式是什么?

3 个答案:

答案 0 :(得分:2)

你可以select来自数组的一组东西(根据它们是否与某些特定代码相匹配),例如,假设你只想找到所有单一颜色的动物:

matching_animals = array2.select {|animal| animal.color == my_color }

在匹配的动物中,你拥有my_color

的所有动物

如果你想要所有动物都是&#34;第一个阵列中的任何颜色&#34;然后你可以这样做:

ok_colors = array1.map{|a| a.color } # pulls out all the colours allowed
matching_animals = array2.select {|animal| ok_colors.include?(animal.color) }

现在您有了一组匹配的动物 - 然后您可以将它们添加到原始数组中:

array1 += matching_animals

并使用以下命令从第二个数组中删除它们:

array2 -= matching_animals

答案 1 :(得分:1)

[编辑:我的答案与之前发布的@ TayrnEast&#39相同。我怀疑在她进行编辑之前我开始在我的工作,直到现在我才注意到编辑。不过,我会留下我的答案,因为我给出的例子可能会引起一些读者的兴趣。]

我原以为你希望array2中的每只动物最多移动到array1一次,在这种情况下,我们会移动一个&#34; blue&#34;动物从array2array1,如果array1中至少有一只蓝色动物。如果我的理解是正确的,你可以这样做。

<强>代码

def add_em(array1, array2)
  colors = array1.map(&:color).uniq
  array1 + array2.select { |e| colors.include?(e) }
end

示例

class A
  attr_reader :name, :color
  def initialize(name, color)
    @name = name
    @color = color
  end
end

blackbird  = A.new("blackbird",  :black)
redbird    = A.new("redbird",    :red)
bluebird   = A.new("bluebird",   :blue)

array1 = [blackbird, redbird, bluebird]

orangetoad = A.new("orangetoad", :orange)
bluetoad   = A.new("bluetoad",   :blue)
pinktoad   = A.new("pinktoad",   :pink)
bluemouse  = A.new("bluemounse", :blue)

array2 = [orangetoad, bluetoad, pinktoad, bluemouse]

array1 = add_em(array1, array2)
  #=> [#<A:0x00000101128638 @name="blackbird", @color=:black>,
  #    #<A:0x00000101946b30 @name="redbird", @color=:red>,
  #    #<A:0x00000101120d70 @name="bluebird", @color=:blue>,
  #    #<A:0x00000102102b30 @name="bluetoad", @color=:blue>,
  #    #<A:0x000001020faea8 @name="bluemounse", @color=:blue>]
array1.map(&:name)
  #=> ["blackbird", "redbird", "bluebird", "bluetoad", "bluemounse"]

或者,您可以将方法的最后一行更改为:

  array1 += array2.select { |e| colors.include?(e) }

并写:

add_em(array1, array2)
array1.map(&:name)
  #=> ["blackbird", "redbird", "bluebird", "bluetoad", "bluemounse"]

我更喜欢第一个版本,因为修改参数会导致麻烦。

答案 2 :(得分:0)

看一下数组文档: http://www.ruby-doc.org/core-2.1.2/Array.html#method-i-collect

array1 = array1.map{ do your stuff }

array1.map!{ do your stuff } #this one is inplace...

我希望这对你有所帮助。