循环访问对象数组.然后访问对象方法(如果找到正确的方法).否则,在数组中创建一个新对象



我从一个空数组和一个键值哈希开始。

我想迭代哈希并将其与空数组进行比较。如果数组中尚不存在每个 k,v 对的值,我想使用该值创建一个对象,然后访问一个对象方法将键附加到对象内的数组中。

这是我的代码

class Test
   def initialize(name)
     @name = name
     @values = []
   end
   attr_accessor :name
   def values=(value)
     @values << value
   end
   def add(value)
     @values.push(value)
   end

end
l = []
n = {'server_1': 'cluster_x', 'server_2': 'cluster_y', 'server_3': 'cluster_z', 'server_4': 'cluster_x', 'server_5': 'cluster_y'}
n.each do |key, value|
  l.any? do |a|
    if a.name == value
      a.add(key)
    else
      t = Test.new(value)
      t.add(key)
      l << t
    end
  end
end
p l

我希望看到这个:

[
#<Test:0x007ff8d10cd3a8 @name=:cluster_x, @values=["server_1, server_4"]>, 
#<Test:0x007ff8d10cd2e0 @name=:cluster_y, @values=["server_2, server_5"]>, 
#<Test:0x007ff8d10cd1f0 @name=:cluster_z, @values=["server_3"]>
]

相反,我只是得到一个空数组。

我认为不满足条件if a.name == value,然后不调用 add 方法。

@Cyzanfar给了我一个关于要寻找什么的线索,我在这里找到了答案

https://stackoverflow.com/a/34904864/5006720

n.each do |key, value|
    found = l.detect {|e| e.name == value}
    if found
      found.add(key)
    else
      t = Test.new(value)
      t.add(key)
      l << t
    end
end

@ARL你快到了!您需要考虑的最后一件事是found何时实际返回一个对象,因为detect会在某个时候找到一个匹配的对象。

 n.each do |key, value|
    found = l.detect {|e| e.name == value}
    if found
      found.add(key)
    else
      t = Test.new(value)
      t.add(key)
      l << t
    end
end

您实际上只想在返回found时添加Test的新实例nil。此代码应生成所需的输出:

[
#<Test:0x007ff8d10cd3a8 @name=:cluster_x, @values=["server_1, server_4"]>, 
#<Test:0x007ff8d10cd2e0 @name=:cluster_y, @values=["server_2, server_5"]>, 
#<Test:0x007ff8d10cd1f0 @name=:cluster_z, @values=["server_3"]>
]

我在你的代码中观察到两件事:

   def values=(value)
     @values << value
   def add(value)
     @values.push(value)
  • 两种方法做同样的事情,推动一个值,因为<<是一种句法糖意味着推动
  • 您更改了 values= 的含义,这通常是为二传手方法保留的,相当于 attire_writer :values

为了说明在 Ruby 中有很多方法可以做事,我提出以下建议:

class Test
  def initialize(name, value)
    @name   = name
    @values = [value]
  end
  def add(value)
    @values << value
  end
end
h_cluster = {} # intermediate hash whose key is the cluster name
n = {'server_1': 'cluster_x', 'server_2': 'cluster_y', 'server_3': 'cluster_z',
     'server_4': 'cluster_x', 'server_5': 'cluster_y'}
n.each do | server, cluster |
  puts "server=#{server}, cluster=#{cluster}"
  cluster_found = h_cluster[cluster] # does the key exist ? => nil or Test 
                                     # instance with servers list
  puts "cluster_found=#{cluster_found.inspect}"
  if cluster_found
  then # add server to existing cluster
    cluster_found.add(server)
  else # create a new cluster
    h_cluster[cluster] = Test.new(cluster, server)
  end
end
p h_cluster.collect { | cluster, servers | servers }

执行:

$ ruby -w t.rb 
server=server_1, cluster=cluster_x
cluster_found=nil
server=server_2, cluster=cluster_y
cluster_found=nil
server=server_3, cluster=cluster_z
cluster_found=nil
server=server_4, cluster=cluster_x
cluster_found=#<Test:0x007fa7a619ae10 @name="cluster_x", @values=[:server_1]>
server=server_5, cluster=cluster_y
cluster_found=#<Test:0x007fa7a619ac58 @name="cluster_y", @values=[:server_2]>
[#<Test:0x007fa7a619ae10 @name="cluster_x", @values=[:server_1, :server_4]>,
 #<Test:0x007fa7a619ac58 @name="cluster_y", @values=[:server_2, :server_5]>,
 #<Test:0x007fa7a619aac8 @name="cluster_z", @values=[:server_3]>]

最新更新