2017-10-28 40 views
3

我從一個空數組和一個鍵值的哈希開始。遍歷數組對象。然後訪問對象方法,如果找到正確的方法。否則,在數組中創建一個新的對象

我想遍歷哈希並將其與空數組進行比較。如果每個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方法沒有被調用。

+0

''l.any永遠是假的因爲你永遠不會添加任何東西。 – Cyzanfar

+0

可能還想看看'group_by',這裏可能會幫助你,或者可能不會幫助你:'n.group_by {| _,v | v}'或'n.keys.group_by {| key | n [key]}' –

回答

1

@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 
+0

幹得好!我在這裏看到的唯一問題是最後一行'l << t',它會導致'nil'值被添加到數組中,因爲每當'found'返回一個實際對象時,變量't'不會被設置。 – Cyzanfar

+0

@cyzanfar絕對正確,我也注意到了。非常感謝您的建議! – ARL

+0

哦真棒:)剛剛添加了一個答案,沒有看到你最後的評論:)。並找到你的錯誤+1! – Cyzanfar

0

@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 

實際上,你只需要添加的Testfound回報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"]> 
] 
0

我觀察你的代碼兩件事情:

def values=(value) 
    @values << value 

    def add(value) 
    @values.push(value) 
  • 兩種方法做同樣的事情,推着一輛價值,<<是一種句法糖含義推
  • 您已更改values=的含義,該含義通常保留給setter方法,相當於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]>]